Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / ext-all-debug.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15
16
17 (function() {
18     var global = this,
19         objectPrototype = Object.prototype,
20         toString = objectPrototype.toString,
21         enumerables = true,
22         enumerablesTest = { toString: 1 },
23         i;
24
25     if (typeof Ext === 'undefined') {
26         global.Ext = {};
27     }
28
29     Ext.global = global;
30
31     for (i in enumerablesTest) {
32         enumerables = null;
33     }
34
35     if (enumerables) {
36         enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable',
37                        'toLocaleString', 'toString', 'constructor'];
38     }
39
40     
41     Ext.enumerables = enumerables;
42
43     
44     Ext.apply = function(object, config, defaults) {
45         if (defaults) {
46             Ext.apply(object, defaults);
47         }
48
49         if (object && config && typeof config === 'object') {
50             var i, j, k;
51
52             for (i in config) {
53                 object[i] = config[i];
54             }
55
56             if (enumerables) {
57                 for (j = enumerables.length; j--;) {
58                     k = enumerables[j];
59                     if (config.hasOwnProperty(k)) {
60                         object[k] = config[k];
61                     }
62                 }
63             }
64         }
65
66         return object;
67     };
68
69     Ext.buildSettings = Ext.apply({
70         baseCSSPrefix: 'x-',
71         scopeResetCSS: false
72     }, Ext.buildSettings || {});
73
74     Ext.apply(Ext, {
75         
76         emptyFn: function() {},
77
78         baseCSSPrefix: Ext.buildSettings.baseCSSPrefix,
79
80         
81         applyIf: function(object, config) {
82             var property;
83
84             if (object) {
85                 for (property in config) {
86                     if (object[property] === undefined) {
87                         object[property] = config[property];
88                     }
89                 }
90             }
91
92             return object;
93         },
94
95         
96         iterate: function(object, fn, scope) {
97             if (Ext.isEmpty(object)) {
98                 return;
99             }
100
101             if (scope === undefined) {
102                 scope = object;
103             }
104
105             if (Ext.isIterable(object)) {
106                 Ext.Array.each.call(Ext.Array, object, fn, scope);
107             }
108             else {
109                 Ext.Object.each.call(Ext.Object, object, fn, scope);
110             }
111         }
112     });
113
114     Ext.apply(Ext, {
115
116         
117         extend: function() {
118             
119             var objectConstructor = objectPrototype.constructor,
120                 inlineOverrides = function(o) {
121                 for (var m in o) {
122                     if (!o.hasOwnProperty(m)) {
123                         continue;
124                     }
125                     this[m] = o[m];
126                 }
127             };
128
129             return function(subclass, superclass, overrides) {
130                 
131                 if (Ext.isObject(superclass)) {
132                     overrides = superclass;
133                     superclass = subclass;
134                     subclass = overrides.constructor !== objectConstructor ? overrides.constructor : function() {
135                         superclass.apply(this, arguments);
136                     };
137                 }
138
139
140                 
141                 var F = function() {},
142                     subclassProto, superclassProto = superclass.prototype;
143
144                 F.prototype = superclassProto;
145                 subclassProto = subclass.prototype = new F();
146                 subclassProto.constructor = subclass;
147                 subclass.superclass = superclassProto;
148
149                 if (superclassProto.constructor === objectConstructor) {
150                     superclassProto.constructor = superclass;
151                 }
152
153                 subclass.override = function(overrides) {
154                     Ext.override(subclass, overrides);
155                 };
156
157                 subclassProto.override = inlineOverrides;
158                 subclassProto.proto = subclassProto;
159
160                 subclass.override(overrides);
161                 subclass.extend = function(o) {
162                     return Ext.extend(subclass, o);
163                 };
164
165                 return subclass;
166             };
167         }(),
168
169         
170         override: function(cls, overrides) {
171             if (cls.prototype.$className) {
172                 return cls.override(overrides);
173             }
174             else {
175                 Ext.apply(cls.prototype, overrides);
176             }
177         }
178     });
179
180     
181     Ext.apply(Ext, {
182
183         
184         valueFrom: function(value, defaultValue, allowBlank){
185             return Ext.isEmpty(value, allowBlank) ? defaultValue : value;
186         },
187
188         
189         typeOf: function(value) {
190             if (value === null) {
191                 return 'null';
192             }
193
194             var type = typeof value;
195
196             if (type === 'undefined' || type === 'string' || type === 'number' || type === 'boolean') {
197                 return type;
198             }
199
200             var typeToString = toString.call(value);
201
202             switch(typeToString) {
203                 case '[object Array]':
204                     return 'array';
205                 case '[object Date]':
206                     return 'date';
207                 case '[object Boolean]':
208                     return 'boolean';
209                 case '[object Number]':
210                     return 'number';
211                 case '[object RegExp]':
212                     return 'regexp';
213             }
214
215             if (type === 'function') {
216                 return 'function';
217             }
218
219             if (type === 'object') {
220                 if (value.nodeType !== undefined) {
221                     if (value.nodeType === 3) {
222                         return (/\S/).test(value.nodeValue) ? 'textnode' : 'whitespace';
223                     }
224                     else {
225                         return 'element';
226                     }
227                 }
228
229                 return 'object';
230             }
231
232         },
233
234         
235         isEmpty: function(value, allowEmptyString) {
236             return (value === null) || (value === undefined) || (!allowEmptyString ? value === '' : false) || (Ext.isArray(value) && value.length === 0);
237         },
238
239         
240         isArray: ('isArray' in Array) ? Array.isArray : function(value) {
241             return toString.call(value) === '[object Array]';
242         },
243
244         
245         isDate: function(value) {
246             return toString.call(value) === '[object Date]';
247         },
248
249         
250         isObject: (toString.call(null) === '[object Object]') ?
251         function(value) {
252             
253             return value !== null && value !== undefined && toString.call(value) === '[object Object]' && value.ownerDocument === undefined;
254         } :
255         function(value) {
256             return toString.call(value) === '[object Object]';
257         },
258
259         
260         isPrimitive: function(value) {
261             var type = typeof value;
262
263             return type === 'string' || type === 'number' || type === 'boolean';
264         },
265
266         
267         isFunction:
268         
269         
270         (typeof document !== 'undefined' && typeof document.getElementsByTagName('body') === 'function') ? function(value) {
271             return toString.call(value) === '[object Function]';
272         } : function(value) {
273             return typeof value === 'function';
274         },
275
276         
277         isNumber: function(value) {
278             return typeof value === 'number' && isFinite(value);
279         },
280
281         
282         isNumeric: function(value) {
283             return !isNaN(parseFloat(value)) && isFinite(value);
284         },
285
286         
287         isString: function(value) {
288             return typeof value === 'string';
289         },
290
291         
292         isBoolean: function(value) {
293             return typeof value === 'boolean';
294         },
295
296         
297         isElement: function(value) {
298             return value ? value.nodeType === 1 : false;
299         },
300
301         
302         isTextNode: function(value) {
303             return value ? value.nodeName === "#text" : false;
304         },
305
306         
307         isDefined: function(value) {
308             return typeof value !== 'undefined';
309         },
310
311         
312         isIterable: function(value) {
313             return (value && typeof value !== 'string') ? value.length !== undefined : false;
314         }
315     });
316
317     Ext.apply(Ext, {
318
319         
320         clone: function(item) {
321             if (item === null || item === undefined) {
322                 return item;
323             }
324
325             
326             
327             
328             if (item.nodeType && item.cloneNode) {
329                 return item.cloneNode(true);
330             }
331
332             var type = toString.call(item);
333
334             
335             if (type === '[object Date]') {
336                 return new Date(item.getTime());
337             }
338
339             var i, j, k, clone, key;
340
341             
342             if (type === '[object Array]') {
343                 i = item.length;
344
345                 clone = [];
346
347                 while (i--) {
348                     clone[i] = Ext.clone(item[i]);
349                 }
350             }
351             
352             else if (type === '[object Object]' && item.constructor === Object) {
353                 clone = {};
354
355                 for (key in item) {
356                     clone[key] = Ext.clone(item[key]);
357                 }
358
359                 if (enumerables) {
360                     for (j = enumerables.length; j--;) {
361                         k = enumerables[j];
362                         clone[k] = item[k];
363                     }
364                 }
365             }
366
367             return clone || item;
368         },
369
370         
371         getUniqueGlobalNamespace: function() {
372             var uniqueGlobalNamespace = this.uniqueGlobalNamespace;
373
374             if (uniqueGlobalNamespace === undefined) {
375                 var i = 0;
376
377                 do {
378                     uniqueGlobalNamespace = 'ExtBox' + (++i);
379                 } while (Ext.global[uniqueGlobalNamespace] !== undefined);
380
381                 Ext.global[uniqueGlobalNamespace] = Ext;
382                 this.uniqueGlobalNamespace = uniqueGlobalNamespace;
383             }
384
385             return uniqueGlobalNamespace;
386         },
387
388         
389         functionFactory: function() {
390             var args = Array.prototype.slice.call(arguments);
391
392             if (args.length > 0) {
393                 args[args.length - 1] = 'var Ext=window.' + this.getUniqueGlobalNamespace() + ';' +
394                     args[args.length - 1];
395             }
396
397             return Function.prototype.constructor.apply(Function.prototype, args);
398         }
399     });
400
401     
402     Ext.type = Ext.typeOf;
403
404 })();
405
406
407 (function() {
408
409
410 var version = '4.0.7', Version;
411     Ext.Version = Version = Ext.extend(Object, {
412
413         
414         constructor: function(version) {
415             var parts, releaseStartIndex;
416
417             if (version instanceof Version) {
418                 return version;
419             }
420
421             this.version = this.shortVersion = String(version).toLowerCase().replace(/_/g, '.').replace(/[\-+]/g, '');
422
423             releaseStartIndex = this.version.search(/([^\d\.])/);
424
425             if (releaseStartIndex !== -1) {
426                 this.release = this.version.substr(releaseStartIndex, version.length);
427                 this.shortVersion = this.version.substr(0, releaseStartIndex);
428             }
429
430             this.shortVersion = this.shortVersion.replace(/[^\d]/g, '');
431
432             parts = this.version.split('.');
433
434             this.major = parseInt(parts.shift() || 0, 10);
435             this.minor = parseInt(parts.shift() || 0, 10);
436             this.patch = parseInt(parts.shift() || 0, 10);
437             this.build = parseInt(parts.shift() || 0, 10);
438
439             return this;
440         },
441
442         
443         toString: function() {
444             return this.version;
445         },
446
447         
448         valueOf: function() {
449             return this.version;
450         },
451
452         
453         getMajor: function() {
454             return this.major || 0;
455         },
456
457         
458         getMinor: function() {
459             return this.minor || 0;
460         },
461
462         
463         getPatch: function() {
464             return this.patch || 0;
465         },
466
467         
468         getBuild: function() {
469             return this.build || 0;
470         },
471
472         
473         getRelease: function() {
474             return this.release || '';
475         },
476
477         
478         isGreaterThan: function(target) {
479             return Version.compare(this.version, target) === 1;
480         },
481
482         
483         isLessThan: function(target) {
484             return Version.compare(this.version, target) === -1;
485         },
486
487         
488         equals: function(target) {
489             return Version.compare(this.version, target) === 0;
490         },
491
492         
493         match: function(target) {
494             target = String(target);
495             return this.version.substr(0, target.length) === target;
496         },
497
498         
499         toArray: function() {
500             return [this.getMajor(), this.getMinor(), this.getPatch(), this.getBuild(), this.getRelease()];
501         },
502
503         
504         getShortVersion: function() {
505             return this.shortVersion;
506         }
507     });
508
509     Ext.apply(Version, {
510         
511         releaseValueMap: {
512             'dev': -6,
513             'alpha': -5,
514             'a': -5,
515             'beta': -4,
516             'b': -4,
517             'rc': -3,
518             '#': -2,
519             'p': -1,
520             'pl': -1
521         },
522
523         
524         getComponentValue: function(value) {
525             return !value ? 0 : (isNaN(value) ? this.releaseValueMap[value] || value : parseInt(value, 10));
526         },
527
528         
529         compare: function(current, target) {
530             var currentValue, targetValue, i;
531
532             current = new Version(current).toArray();
533             target = new Version(target).toArray();
534
535             for (i = 0; i < Math.max(current.length, target.length); i++) {
536                 currentValue = this.getComponentValue(current[i]);
537                 targetValue = this.getComponentValue(target[i]);
538
539                 if (currentValue < targetValue) {
540                     return -1;
541                 } else if (currentValue > targetValue) {
542                     return 1;
543                 }
544             }
545
546             return 0;
547         }
548     });
549
550     Ext.apply(Ext, {
551         
552         versions: {},
553
554         
555         lastRegisteredVersion: null,
556
557         
558         setVersion: function(packageName, version) {
559             Ext.versions[packageName] = new Version(version);
560             Ext.lastRegisteredVersion = Ext.versions[packageName];
561
562             return this;
563         },
564
565         
566         getVersion: function(packageName) {
567             if (packageName === undefined) {
568                 return Ext.lastRegisteredVersion;
569             }
570
571             return Ext.versions[packageName];
572         },
573
574         
575         deprecate: function(packageName, since, closure, scope) {
576             if (Version.compare(Ext.getVersion(packageName), since) < 1) {
577                 closure.call(scope);
578             }
579         }
580     }); 
581
582     Ext.setVersion('core', version);
583
584 })();
585
586
587
588 Ext.String = {
589     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,
590     escapeRe: /('|\\)/g,
591     formatRe: /\{(\d+)\}/g,
592     escapeRegexRe: /([-.*+?^${}()|[\]\/\\])/g,
593
594     /**
595      * Convert certain characters (&, <, >, and ") to their HTML character equivalents for literal display in web pages.
596      * @param {String} value The string to encode
597      * @return {String} The encoded text
598      * @method
599      */
600     htmlEncode: (function() {
601         var entities = {
602             '&': '&amp;',
603             '>': '&gt;',
604             '<': '&lt;',
605             '"': '&quot;'
606         }, keys = [], p, regex;
607         
608         for (p in entities) {
609             keys.push(p);
610         }
611         
612         regex = new RegExp('(' + keys.join('|') + ')', 'g');
613         
614         return function(value) {
615             return (!value) ? value : String(value).replace(regex, function(match, capture) {
616                 return entities[capture];    
617             });
618         };
619     })(),
620
621     /**
622      * Convert certain characters (&, <, >, and ") from their HTML character equivalents.
623      * @param {String} value The string to decode
624      * @return {String} The decoded text
625      * @method
626      */
627     htmlDecode: (function() {
628         var entities = {
629             '&amp;': '&',
630             '&gt;': '>',
631             '&lt;': '<',
632             '&quot;': '"'
633         }, keys = [], p, regex;
634         
635         for (p in entities) {
636             keys.push(p);
637         }
638         
639         regex = new RegExp('(' + keys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
640         
641         return function(value) {
642             return (!value) ? value : String(value).replace(regex, function(match, capture) {
643                 if (capture in entities) {
644                     return entities[capture];
645                 } else {
646                     return String.fromCharCode(parseInt(capture.substr(2), 10));
647                 }
648             });
649         };
650     })(),
651
652     
653     urlAppend : function(url, string) {
654         if (!Ext.isEmpty(string)) {
655             return url + (url.indexOf('?') === -1 ? '?' : '&') + string;
656         }
657
658         return url;
659     },
660
661     
662     trim: function(string) {
663         return string.replace(Ext.String.trimRegex, "");
664     },
665
666     
667     capitalize: function(string) {
668         return string.charAt(0).toUpperCase() + string.substr(1);
669     },
670
671     
672     ellipsis: function(value, len, word) {
673         if (value && value.length > len) {
674             if (word) {
675                 var vs = value.substr(0, len - 2),
676                 index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));
677                 if (index !== -1 && index >= (len - 15)) {
678                     return vs.substr(0, index) + "...";
679                 }
680             }
681             return value.substr(0, len - 3) + "...";
682         }
683         return value;
684     },
685
686     
687     escapeRegex: function(string) {
688         return string.replace(Ext.String.escapeRegexRe, "\\$1");
689     },
690
691     
692     escape: function(string) {
693         return string.replace(Ext.String.escapeRe, "\\$1");
694     },
695
696     
697     toggle: function(string, value, other) {
698         return string === value ? other : value;
699     },
700
701     
702     leftPad: function(string, size, character) {
703         var result = String(string);
704         character = character || " ";
705         while (result.length < size) {
706             result = character + result;
707         }
708         return result;
709     },
710
711     
712     format: function(format) {
713         var args = Ext.Array.toArray(arguments, 1);
714         return format.replace(Ext.String.formatRe, function(m, i) {
715             return args[i];
716         });
717     },
718
719     
720     repeat: function(pattern, count, sep) {
721         for (var buf = [], i = count; i--; ) {
722             buf.push(pattern);
723         }
724         return buf.join(sep || '');
725     }
726 };
727
728
729
730 (function() {
731
732 var isToFixedBroken = (0.9).toFixed() !== '1';
733
734 Ext.Number = {
735     
736     constrain: function(number, min, max) {
737         number = parseFloat(number);
738
739         if (!isNaN(min)) {
740             number = Math.max(number, min);
741         }
742         if (!isNaN(max)) {
743             number = Math.min(number, max);
744         }
745         return number;
746     },
747
748     
749     snap : function(value, increment, minValue, maxValue) {
750         var newValue = value,
751             m;
752
753         if (!(increment && value)) {
754             return value;
755         }
756         m = value % increment;
757         if (m !== 0) {
758             newValue -= m;
759             if (m * 2 >= increment) {
760                 newValue += increment;
761             } else if (m * 2 < -increment) {
762                 newValue -= increment;
763             }
764         }
765         return Ext.Number.constrain(newValue, minValue,  maxValue);
766     },
767
768     
769     toFixed: function(value, precision) {
770         if (isToFixedBroken) {
771             precision = precision || 0;
772             var pow = Math.pow(10, precision);
773             return (Math.round(value * pow) / pow).toFixed(precision);
774         }
775
776         return value.toFixed(precision);
777     },
778
779     
780     from: function(value, defaultValue) {
781         if (isFinite(value)) {
782             value = parseFloat(value);
783         }
784
785         return !isNaN(value) ? value : defaultValue;
786     }
787 };
788
789 })();
790
791
792 Ext.num = function() {
793     return Ext.Number.from.apply(this, arguments);
794 };
795
796 (function() {
797
798     var arrayPrototype = Array.prototype,
799         slice = arrayPrototype.slice,
800         supportsSplice = function () {
801             var array = [],
802                 lengthBefore,
803                 j = 20;
804
805             if (!array.splice) {
806                 return false;
807             }
808
809             
810             
811
812             while (j--) {
813                 array.push("A");
814             }
815
816             array.splice(15, 0, "F", "F", "F", "F", "F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F");
817
818             lengthBefore = array.length; 
819             array.splice(13, 0, "XXX"); 
820
821             if (lengthBefore+1 != array.length) {
822                 return false;
823             }
824             
825
826             return true;
827         }(),
828         supportsForEach = 'forEach' in arrayPrototype,
829         supportsMap = 'map' in arrayPrototype,
830         supportsIndexOf = 'indexOf' in arrayPrototype,
831         supportsEvery = 'every' in arrayPrototype,
832         supportsSome = 'some' in arrayPrototype,
833         supportsFilter = 'filter' in arrayPrototype,
834         supportsSort = function() {
835             var a = [1,2,3,4,5].sort(function(){ return 0; });
836             return a[0] === 1 && a[1] === 2 && a[2] === 3 && a[3] === 4 && a[4] === 5;
837         }(),
838         supportsSliceOnNodeList = true,
839         ExtArray;
840
841     try {
842         
843         if (typeof document !== 'undefined') {
844             slice.call(document.getElementsByTagName('body'));
845         }
846     } catch (e) {
847         supportsSliceOnNodeList = false;
848     }
849
850     function fixArrayIndex (array, index) {
851         return (index < 0) ? Math.max(0, array.length + index)
852                            : Math.min(array.length, index);
853     }
854
855     
856     function replaceSim (array, index, removeCount, insert) {
857         var add = insert ? insert.length : 0,
858             length = array.length,
859             pos = fixArrayIndex(array, index);
860
861         
862         if (pos === length) {
863             if (add) {
864                 array.push.apply(array, insert);
865             }
866         } else {
867             var remove = Math.min(removeCount, length - pos),
868                 tailOldPos = pos + remove,
869                 tailNewPos = tailOldPos + add - remove,
870                 tailCount = length - tailOldPos,
871                 lengthAfterRemove = length - remove,
872                 i;
873
874             if (tailNewPos < tailOldPos) { 
875                 for (i = 0; i < tailCount; ++i) {
876                     array[tailNewPos+i] = array[tailOldPos+i];
877                 }
878             } else if (tailNewPos > tailOldPos) { 
879                 for (i = tailCount; i--; ) {
880                     array[tailNewPos+i] = array[tailOldPos+i];
881                 }
882             } 
883
884             if (add && pos === lengthAfterRemove) {
885                 array.length = lengthAfterRemove; 
886                 array.push.apply(array, insert);
887             } else {
888                 array.length = lengthAfterRemove + add; 
889                 for (i = 0; i < add; ++i) {
890                     array[pos+i] = insert[i];
891                 }
892             }
893         }
894
895         return array;
896     }
897
898     function replaceNative (array, index, removeCount, insert) {
899         if (insert && insert.length) {
900             if (index < array.length) {
901                 array.splice.apply(array, [index, removeCount].concat(insert));
902             } else {
903                 array.push.apply(array, insert);
904             }
905         } else {
906             array.splice(index, removeCount);
907         }
908         return array;
909     }
910
911     function eraseSim (array, index, removeCount) {
912         return replaceSim(array, index, removeCount);
913     }
914
915     function eraseNative (array, index, removeCount) {
916         array.splice(index, removeCount);
917         return array;
918     }
919
920     function spliceSim (array, index, removeCount) {
921         var pos = fixArrayIndex(array, index),
922             removed = array.slice(index, fixArrayIndex(array, pos+removeCount));
923
924         if (arguments.length < 4) {
925             replaceSim(array, pos, removeCount);
926         } else {
927             replaceSim(array, pos, removeCount, slice.call(arguments, 3));
928         }
929
930         return removed;
931     }
932
933     function spliceNative (array) {
934         return array.splice.apply(array, slice.call(arguments, 1));
935     }
936
937     var erase = supportsSplice ? eraseNative : eraseSim,
938         replace = supportsSplice ? replaceNative : replaceSim,
939         splice = supportsSplice ? spliceNative : spliceSim;
940
941     
942
943     ExtArray = Ext.Array = {
944         
945         each: function(array, fn, scope, reverse) {
946             array = ExtArray.from(array);
947
948             var i,
949                 ln = array.length;
950
951             if (reverse !== true) {
952                 for (i = 0; i < ln; i++) {
953                     if (fn.call(scope || array[i], array[i], i, array) === false) {
954                         return i;
955                     }
956                 }
957             }
958             else {
959                 for (i = ln - 1; i > -1; i--) {
960                     if (fn.call(scope || array[i], array[i], i, array) === false) {
961                         return i;
962                     }
963                 }
964             }
965
966             return true;
967         },
968
969         
970         forEach: function(array, fn, scope) {
971             if (supportsForEach) {
972                 return array.forEach(fn, scope);
973             }
974
975             var i = 0,
976                 ln = array.length;
977
978             for (; i < ln; i++) {
979                 fn.call(scope, array[i], i, array);
980             }
981         },
982
983         
984         indexOf: function(array, item, from) {
985             if (supportsIndexOf) {
986                 return array.indexOf(item, from);
987             }
988
989             var i, length = array.length;
990
991             for (i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++) {
992                 if (array[i] === item) {
993                     return i;
994                 }
995             }
996
997             return -1;
998         },
999
1000         
1001         contains: function(array, item) {
1002             if (supportsIndexOf) {
1003                 return array.indexOf(item) !== -1;
1004             }
1005
1006             var i, ln;
1007
1008             for (i = 0, ln = array.length; i < ln; i++) {
1009                 if (array[i] === item) {
1010                     return true;
1011                 }
1012             }
1013
1014             return false;
1015         },
1016
1017         
1018         toArray: function(iterable, start, end){
1019             if (!iterable || !iterable.length) {
1020                 return [];
1021             }
1022
1023             if (typeof iterable === 'string') {
1024                 iterable = iterable.split('');
1025             }
1026
1027             if (supportsSliceOnNodeList) {
1028                 return slice.call(iterable, start || 0, end || iterable.length);
1029             }
1030
1031             var array = [],
1032                 i;
1033
1034             start = start || 0;
1035             end = end ? ((end < 0) ? iterable.length + end : end) : iterable.length;
1036
1037             for (i = start; i < end; i++) {
1038                 array.push(iterable[i]);
1039             }
1040
1041             return array;
1042         },
1043
1044         
1045         pluck: function(array, propertyName) {
1046             var ret = [],
1047                 i, ln, item;
1048
1049             for (i = 0, ln = array.length; i < ln; i++) {
1050                 item = array[i];
1051
1052                 ret.push(item[propertyName]);
1053             }
1054
1055             return ret;
1056         },
1057
1058         
1059         map: function(array, fn, scope) {
1060             if (supportsMap) {
1061                 return array.map(fn, scope);
1062             }
1063
1064             var results = [],
1065                 i = 0,
1066                 len = array.length;
1067
1068             for (; i < len; i++) {
1069                 results[i] = fn.call(scope, array[i], i, array);
1070             }
1071
1072             return results;
1073         },
1074
1075         
1076         every: function(array, fn, scope) {
1077             if (supportsEvery) {
1078                 return array.every(fn, scope);
1079             }
1080
1081             var i = 0,
1082                 ln = array.length;
1083
1084             for (; i < ln; ++i) {
1085                 if (!fn.call(scope, array[i], i, array)) {
1086                     return false;
1087                 }
1088             }
1089
1090             return true;
1091         },
1092
1093         
1094         some: function(array, fn, scope) {
1095             if (supportsSome) {
1096                 return array.some(fn, scope);
1097             }
1098
1099             var i = 0,
1100                 ln = array.length;
1101
1102             for (; i < ln; ++i) {
1103                 if (fn.call(scope, array[i], i, array)) {
1104                     return true;
1105                 }
1106             }
1107
1108             return false;
1109         },
1110
1111         
1112         clean: function(array) {
1113             var results = [],
1114                 i = 0,
1115                 ln = array.length,
1116                 item;
1117
1118             for (; i < ln; i++) {
1119                 item = array[i];
1120
1121                 if (!Ext.isEmpty(item)) {
1122                     results.push(item);
1123                 }
1124             }
1125
1126             return results;
1127         },
1128
1129         
1130         unique: function(array) {
1131             var clone = [],
1132                 i = 0,
1133                 ln = array.length,
1134                 item;
1135
1136             for (; i < ln; i++) {
1137                 item = array[i];
1138
1139                 if (ExtArray.indexOf(clone, item) === -1) {
1140                     clone.push(item);
1141                 }
1142             }
1143
1144             return clone;
1145         },
1146
1147         
1148         filter: function(array, fn, scope) {
1149             if (supportsFilter) {
1150                 return array.filter(fn, scope);
1151             }
1152
1153             var results = [],
1154                 i = 0,
1155                 ln = array.length;
1156
1157             for (; i < ln; i++) {
1158                 if (fn.call(scope, array[i], i, array)) {
1159                     results.push(array[i]);
1160                 }
1161             }
1162
1163             return results;
1164         },
1165
1166         
1167         from: function(value, newReference) {
1168             if (value === undefined || value === null) {
1169                 return [];
1170             }
1171
1172             if (Ext.isArray(value)) {
1173                 return (newReference) ? slice.call(value) : value;
1174             }
1175
1176             if (value && value.length !== undefined && typeof value !== 'string') {
1177                 return Ext.toArray(value);
1178             }
1179
1180             return [value];
1181         },
1182
1183         
1184         remove: function(array, item) {
1185             var index = ExtArray.indexOf(array, item);
1186
1187             if (index !== -1) {
1188                 erase(array, index, 1);
1189             }
1190
1191             return array;
1192         },
1193
1194         
1195         include: function(array, item) {
1196             if (!ExtArray.contains(array, item)) {
1197                 array.push(item);
1198             }
1199         },
1200
1201         
1202         clone: function(array) {
1203             return slice.call(array);
1204         },
1205
1206         
1207         merge: function() {
1208             var args = slice.call(arguments),
1209                 array = [],
1210                 i, ln;
1211
1212             for (i = 0, ln = args.length; i < ln; i++) {
1213                 array = array.concat(args[i]);
1214             }
1215
1216             return ExtArray.unique(array);
1217         },
1218
1219         
1220         intersect: function() {
1221             var intersect = [],
1222                 arrays = slice.call(arguments),
1223                 i, j, k, minArray, array, x, y, ln, arraysLn, arrayLn;
1224
1225             if (!arrays.length) {
1226                 return intersect;
1227             }
1228
1229             
1230             for (i = x = 0,ln = arrays.length; i < ln,array = arrays[i]; i++) {
1231                 if (!minArray || array.length < minArray.length) {
1232                     minArray = array;
1233                     x = i;
1234                 }
1235             }
1236
1237             minArray = ExtArray.unique(minArray);
1238             erase(arrays, x, 1);
1239
1240             
1241             
1242             
1243             for (i = 0,ln = minArray.length; i < ln,x = minArray[i]; i++) {
1244                 var count = 0;
1245
1246                 for (j = 0,arraysLn = arrays.length; j < arraysLn,array = arrays[j]; j++) {
1247                     for (k = 0,arrayLn = array.length; k < arrayLn,y = array[k]; k++) {
1248                         if (x === y) {
1249                             count++;
1250                             break;
1251                         }
1252                     }
1253                 }
1254
1255                 if (count === arraysLn) {
1256                     intersect.push(x);
1257                 }
1258             }
1259
1260             return intersect;
1261         },
1262
1263         
1264         difference: function(arrayA, arrayB) {
1265             var clone = slice.call(arrayA),
1266                 ln = clone.length,
1267                 i, j, lnB;
1268
1269             for (i = 0,lnB = arrayB.length; i < lnB; i++) {
1270                 for (j = 0; j < ln; j++) {
1271                     if (clone[j] === arrayB[i]) {
1272                         erase(clone, j, 1);
1273                         j--;
1274                         ln--;
1275                     }
1276                 }
1277             }
1278
1279             return clone;
1280         },
1281
1282         
1283         
1284         slice: ([1,2].slice(1, undefined).length ?
1285             function (array, begin, end) {
1286                 return slice.call(array, begin, end);
1287             } :
1288             
1289             function (array, begin, end) {
1290                 
1291                 
1292                 if (typeof begin === 'undefined') {
1293                     return slice.call(array);
1294                 }
1295                 if (typeof end === 'undefined') {
1296                     return slice.call(array, begin);
1297                 }
1298                 return slice.call(array, begin, end);
1299             }
1300         ),
1301
1302         
1303         sort: function(array, sortFn) {
1304             if (supportsSort) {
1305                 if (sortFn) {
1306                     return array.sort(sortFn);
1307                 } else {
1308                     return array.sort();
1309                 }
1310             }
1311
1312             var length = array.length,
1313                 i = 0,
1314                 comparison,
1315                 j, min, tmp;
1316
1317             for (; i < length; i++) {
1318                 min = i;
1319                 for (j = i + 1; j < length; j++) {
1320                     if (sortFn) {
1321                         comparison = sortFn(array[j], array[min]);
1322                         if (comparison < 0) {
1323                             min = j;
1324                         }
1325                     } else if (array[j] < array[min]) {
1326                         min = j;
1327                     }
1328                 }
1329                 if (min !== i) {
1330                     tmp = array[i];
1331                     array[i] = array[min];
1332                     array[min] = tmp;
1333                 }
1334             }
1335
1336             return array;
1337         },
1338
1339         
1340         flatten: function(array) {
1341             var worker = [];
1342
1343             function rFlatten(a) {
1344                 var i, ln, v;
1345
1346                 for (i = 0, ln = a.length; i < ln; i++) {
1347                     v = a[i];
1348
1349                     if (Ext.isArray(v)) {
1350                         rFlatten(v);
1351                     } else {
1352                         worker.push(v);
1353                     }
1354                 }
1355
1356                 return worker;
1357             }
1358
1359             return rFlatten(array);
1360         },
1361
1362         
1363         min: function(array, comparisonFn) {
1364             var min = array[0],
1365                 i, ln, item;
1366
1367             for (i = 0, ln = array.length; i < ln; i++) {
1368                 item = array[i];
1369
1370                 if (comparisonFn) {
1371                     if (comparisonFn(min, item) === 1) {
1372                         min = item;
1373                     }
1374                 }
1375                 else {
1376                     if (item < min) {
1377                         min = item;
1378                     }
1379                 }
1380             }
1381
1382             return min;
1383         },
1384
1385         
1386         max: function(array, comparisonFn) {
1387             var max = array[0],
1388                 i, ln, item;
1389
1390             for (i = 0, ln = array.length; i < ln; i++) {
1391                 item = array[i];
1392
1393                 if (comparisonFn) {
1394                     if (comparisonFn(max, item) === -1) {
1395                         max = item;
1396                     }
1397                 }
1398                 else {
1399                     if (item > max) {
1400                         max = item;
1401                     }
1402                 }
1403             }
1404
1405             return max;
1406         },
1407
1408         
1409         mean: function(array) {
1410             return array.length > 0 ? ExtArray.sum(array) / array.length : undefined;
1411         },
1412
1413         
1414         sum: function(array) {
1415             var sum = 0,
1416                 i, ln, item;
1417
1418             for (i = 0,ln = array.length; i < ln; i++) {
1419                 item = array[i];
1420
1421                 sum += item;
1422             }
1423
1424             return sum;
1425         },
1426
1427
1428         
1429         erase: erase,
1430
1431         
1432         insert: function (array, index, items) {
1433             return replace(array, index, 0, items);
1434         },
1435
1436         
1437         replace: replace,
1438
1439         
1440         splice: splice
1441     };
1442
1443     
1444     Ext.each = ExtArray.each;
1445
1446     
1447     ExtArray.union = ExtArray.merge;
1448
1449     
1450     Ext.min = ExtArray.min;
1451
1452     
1453     Ext.max = ExtArray.max;
1454
1455     
1456     Ext.sum = ExtArray.sum;
1457
1458     
1459     Ext.mean = ExtArray.mean;
1460
1461     
1462     Ext.flatten = ExtArray.flatten;
1463
1464     
1465     Ext.clean = ExtArray.clean;
1466
1467     
1468     Ext.unique = ExtArray.unique;
1469
1470     
1471     Ext.pluck = ExtArray.pluck;
1472
1473     
1474     Ext.toArray = function() {
1475         return ExtArray.toArray.apply(ExtArray, arguments);
1476     };
1477 })();
1478
1479
1480 Ext.Function = {
1481
1482     
1483     flexSetter: function(fn) {
1484         return function(a, b) {
1485             var k, i;
1486
1487             if (a === null) {
1488                 return this;
1489             }
1490
1491             if (typeof a !== 'string') {
1492                 for (k in a) {
1493                     if (a.hasOwnProperty(k)) {
1494                         fn.call(this, k, a[k]);
1495                     }
1496                 }
1497
1498                 if (Ext.enumerables) {
1499                     for (i = Ext.enumerables.length; i--;) {
1500                         k = Ext.enumerables[i];
1501                         if (a.hasOwnProperty(k)) {
1502                             fn.call(this, k, a[k]);
1503                         }
1504                     }
1505                 }
1506             } else {
1507                 fn.call(this, a, b);
1508             }
1509
1510             return this;
1511         };
1512     },
1513
1514     
1515     bind: function(fn, scope, args, appendArgs) {
1516         if (arguments.length === 2) {
1517             return function() {
1518                 return fn.apply(scope, arguments);
1519             }
1520         }
1521
1522         var method = fn,
1523             slice = Array.prototype.slice;
1524
1525         return function() {
1526             var callArgs = args || arguments;
1527
1528             if (appendArgs === true) {
1529                 callArgs = slice.call(arguments, 0);
1530                 callArgs = callArgs.concat(args);
1531             }
1532             else if (typeof appendArgs == 'number') {
1533                 callArgs = slice.call(arguments, 0); 
1534                 Ext.Array.insert(callArgs, appendArgs, args);
1535             }
1536
1537             return method.apply(scope || window, callArgs);
1538         };
1539     },
1540
1541     
1542     pass: function(fn, args, scope) {
1543         if (args) {
1544             args = Ext.Array.from(args);
1545         }
1546
1547         return function() {
1548             return fn.apply(scope, args.concat(Ext.Array.toArray(arguments)));
1549         };
1550     },
1551
1552     
1553     alias: function(object, methodName) {
1554         return function() {
1555             return object[methodName].apply(object, arguments);
1556         };
1557     },
1558
1559     
1560     createInterceptor: function(origFn, newFn, scope, returnValue) {
1561         var method = origFn;
1562         if (!Ext.isFunction(newFn)) {
1563             return origFn;
1564         }
1565         else {
1566             return function() {
1567                 var me = this,
1568                     args = arguments;
1569                 newFn.target = me;
1570                 newFn.method = origFn;
1571                 return (newFn.apply(scope || me || window, args) !== false) ? origFn.apply(me || window, args) : returnValue || null;
1572             };
1573         }
1574     },
1575
1576     
1577     createDelayed: function(fn, delay, scope, args, appendArgs) {
1578         if (scope || args) {
1579             fn = Ext.Function.bind(fn, scope, args, appendArgs);
1580         }
1581         return function() {
1582             var me = this;
1583             setTimeout(function() {
1584                 fn.apply(me, arguments);
1585             }, delay);
1586         };
1587     },
1588
1589     
1590     defer: function(fn, millis, obj, args, appendArgs) {
1591         fn = Ext.Function.bind(fn, obj, args, appendArgs);
1592         if (millis > 0) {
1593             return setTimeout(fn, millis);
1594         }
1595         fn();
1596         return 0;
1597     },
1598
1599     
1600     createSequence: function(origFn, newFn, scope) {
1601         if (!Ext.isFunction(newFn)) {
1602             return origFn;
1603         }
1604         else {
1605             return function() {
1606                 var retval = origFn.apply(this || window, arguments);
1607                 newFn.apply(scope || this || window, arguments);
1608                 return retval;
1609             };
1610         }
1611     },
1612
1613     
1614     createBuffered: function(fn, buffer, scope, args) {
1615         return function(){
1616             var timerId;
1617             return function() {
1618                 var me = this;
1619                 if (timerId) {
1620                     clearTimeout(timerId);
1621                     timerId = null;
1622                 }
1623                 timerId = setTimeout(function(){
1624                     fn.apply(scope || me, args || arguments);
1625                 }, buffer);
1626             };
1627         }();
1628     },
1629
1630     
1631     createThrottled: function(fn, interval, scope) {
1632         var lastCallTime, elapsed, lastArgs, timer, execute = function() {
1633             fn.apply(scope || this, lastArgs);
1634             lastCallTime = new Date().getTime();
1635         };
1636
1637         return function() {
1638             elapsed = new Date().getTime() - lastCallTime;
1639             lastArgs = arguments;
1640
1641             clearTimeout(timer);
1642             if (!lastCallTime || (elapsed >= interval)) {
1643                 execute();
1644             } else {
1645                 timer = setTimeout(execute, interval - elapsed);
1646             }
1647         };
1648     },
1649
1650     
1651     interceptBefore: function(object, methodName, fn) {
1652         var method = object[methodName] || Ext.emptyFn;
1653
1654         return object[methodName] = function() {
1655             var ret = fn.apply(this, arguments);
1656             method.apply(this, arguments);
1657
1658             return ret;
1659         };
1660     },
1661
1662     
1663     interceptAfter: function(object, methodName, fn) {
1664         var method = object[methodName] || Ext.emptyFn;
1665
1666         return object[methodName] = function() {
1667             method.apply(this, arguments);
1668             return fn.apply(this, arguments);
1669         };
1670     }
1671 };
1672
1673
1674 Ext.defer = Ext.Function.alias(Ext.Function, 'defer');
1675
1676
1677 Ext.pass = Ext.Function.alias(Ext.Function, 'pass');
1678
1679
1680 Ext.bind = Ext.Function.alias(Ext.Function, 'bind');
1681
1682
1683
1684 (function() {
1685
1686 var ExtObject = Ext.Object = {
1687
1688     
1689     toQueryObjects: function(name, value, recursive) {
1690         var self = ExtObject.toQueryObjects,
1691             objects = [],
1692             i, ln;
1693
1694         if (Ext.isArray(value)) {
1695             for (i = 0, ln = value.length; i < ln; i++) {
1696                 if (recursive) {
1697                     objects = objects.concat(self(name + '[' + i + ']', value[i], true));
1698                 }
1699                 else {
1700                     objects.push({
1701                         name: name,
1702                         value: value[i]
1703                     });
1704                 }
1705             }
1706         }
1707         else if (Ext.isObject(value)) {
1708             for (i in value) {
1709                 if (value.hasOwnProperty(i)) {
1710                     if (recursive) {
1711                         objects = objects.concat(self(name + '[' + i + ']', value[i], true));
1712                     }
1713                     else {
1714                         objects.push({
1715                             name: name,
1716                             value: value[i]
1717                         });
1718                     }
1719                 }
1720             }
1721         }
1722         else {
1723             objects.push({
1724                 name: name,
1725                 value: value
1726             });
1727         }
1728
1729         return objects;
1730     },
1731
1732     
1733     toQueryString: function(object, recursive) {
1734         var paramObjects = [],
1735             params = [],
1736             i, j, ln, paramObject, value;
1737
1738         for (i in object) {
1739             if (object.hasOwnProperty(i)) {
1740                 paramObjects = paramObjects.concat(ExtObject.toQueryObjects(i, object[i], recursive));
1741             }
1742         }
1743
1744         for (j = 0, ln = paramObjects.length; j < ln; j++) {
1745             paramObject = paramObjects[j];
1746             value = paramObject.value;
1747
1748             if (Ext.isEmpty(value)) {
1749                 value = '';
1750             }
1751             else if (Ext.isDate(value)) {
1752                 value = Ext.Date.toString(value);
1753             }
1754
1755             params.push(encodeURIComponent(paramObject.name) + '=' + encodeURIComponent(String(value)));
1756         }
1757
1758         return params.join('&');
1759     },
1760
1761     
1762     fromQueryString: function(queryString, recursive) {
1763         var parts = queryString.replace(/^\?/, '').split('&'),
1764             object = {},
1765             temp, components, name, value, i, ln,
1766             part, j, subLn, matchedKeys, matchedName,
1767             keys, key, nextKey;
1768
1769         for (i = 0, ln = parts.length; i < ln; i++) {
1770             part = parts[i];
1771
1772             if (part.length > 0) {
1773                 components = part.split('=');
1774                 name = decodeURIComponent(components[0]);
1775                 value = (components[1] !== undefined) ? decodeURIComponent(components[1]) : '';
1776
1777                 if (!recursive) {
1778                     if (object.hasOwnProperty(name)) {
1779                         if (!Ext.isArray(object[name])) {
1780                             object[name] = [object[name]];
1781                         }
1782
1783                         object[name].push(value);
1784                     }
1785                     else {
1786                         object[name] = value;
1787                     }
1788                 }
1789                 else {
1790                     matchedKeys = name.match(/(\[):?([^\]]*)\]/g);
1791                     matchedName = name.match(/^([^\[]+)/);
1792
1793
1794                     name = matchedName[0];
1795                     keys = [];
1796
1797                     if (matchedKeys === null) {
1798                         object[name] = value;
1799                         continue;
1800                     }
1801
1802                     for (j = 0, subLn = matchedKeys.length; j < subLn; j++) {
1803                         key = matchedKeys[j];
1804                         key = (key.length === 2) ? '' : key.substring(1, key.length - 1);
1805                         keys.push(key);
1806                     }
1807
1808                     keys.unshift(name);
1809
1810                     temp = object;
1811
1812                     for (j = 0, subLn = keys.length; j < subLn; j++) {
1813                         key = keys[j];
1814
1815                         if (j === subLn - 1) {
1816                             if (Ext.isArray(temp) && key === '') {
1817                                 temp.push(value);
1818                             }
1819                             else {
1820                                 temp[key] = value;
1821                             }
1822                         }
1823                         else {
1824                             if (temp[key] === undefined || typeof temp[key] === 'string') {
1825                                 nextKey = keys[j+1];
1826
1827                                 temp[key] = (Ext.isNumeric(nextKey) || nextKey === '') ? [] : {};
1828                             }
1829
1830                             temp = temp[key];
1831                         }
1832                     }
1833                 }
1834             }
1835         }
1836
1837         return object;
1838     },
1839
1840     
1841     each: function(object, fn, scope) {
1842         for (var property in object) {
1843             if (object.hasOwnProperty(property)) {
1844                 if (fn.call(scope || object, property, object[property], object) === false) {
1845                     return;
1846                 }
1847             }
1848         }
1849     },
1850
1851     
1852     merge: function(source, key, value) {
1853         if (typeof key === 'string') {
1854             if (value && value.constructor === Object) {
1855                 if (source[key] && source[key].constructor === Object) {
1856                     ExtObject.merge(source[key], value);
1857                 }
1858                 else {
1859                     source[key] = Ext.clone(value);
1860                 }
1861             }
1862             else {
1863                 source[key] = value;
1864             }
1865
1866             return source;
1867         }
1868
1869         var i = 1,
1870             ln = arguments.length,
1871             object, property;
1872
1873         for (; i < ln; i++) {
1874             object = arguments[i];
1875
1876             for (property in object) {
1877                 if (object.hasOwnProperty(property)) {
1878                     ExtObject.merge(source, property, object[property]);
1879                 }
1880             }
1881         }
1882
1883         return source;
1884     },
1885
1886     
1887     getKey: function(object, value) {
1888         for (var property in object) {
1889             if (object.hasOwnProperty(property) && object[property] === value) {
1890                 return property;
1891             }
1892         }
1893
1894         return null;
1895     },
1896
1897     
1898     getValues: function(object) {
1899         var values = [],
1900             property;
1901
1902         for (property in object) {
1903             if (object.hasOwnProperty(property)) {
1904                 values.push(object[property]);
1905             }
1906         }
1907
1908         return values;
1909     },
1910
1911     
1912     getKeys: ('keys' in Object.prototype) ? Object.keys : function(object) {
1913         var keys = [],
1914             property;
1915
1916         for (property in object) {
1917             if (object.hasOwnProperty(property)) {
1918                 keys.push(property);
1919             }
1920         }
1921
1922         return keys;
1923     },
1924
1925     
1926     getSize: function(object) {
1927         var size = 0,
1928             property;
1929
1930         for (property in object) {
1931             if (object.hasOwnProperty(property)) {
1932                 size++;
1933             }
1934         }
1935
1936         return size;
1937     }
1938 };
1939
1940
1941
1942 Ext.merge = Ext.Object.merge;
1943
1944
1945 Ext.urlEncode = function() {
1946     var args = Ext.Array.from(arguments),
1947         prefix = '';
1948
1949     
1950     if ((typeof args[1] === 'string')) {
1951         prefix = args[1] + '&';
1952         args[1] = false;
1953     }
1954
1955     return prefix + Ext.Object.toQueryString.apply(Ext.Object, args);
1956 };
1957
1958
1959 Ext.urlDecode = function() {
1960     return Ext.Object.fromQueryString.apply(Ext.Object, arguments);
1961 };
1962
1963 })();
1964
1965
1966
1967
1968
1969 (function() {
1970
1971
1972
1973
1974 function xf(format) {
1975     var args = Array.prototype.slice.call(arguments, 1);
1976     return format.replace(/\{(\d+)\}/g, function(m, i) {
1977         return args[i];
1978     });
1979 }
1980
1981 Ext.Date = {
1982     
1983     now: Date.now || function() {
1984         return +new Date();
1985     },
1986
1987     
1988     toString: function(date) {
1989         var pad = Ext.String.leftPad;
1990
1991         return date.getFullYear() + "-"
1992             + pad(date.getMonth() + 1, 2, '0') + "-"
1993             + pad(date.getDate(), 2, '0') + "T"
1994             + pad(date.getHours(), 2, '0') + ":"
1995             + pad(date.getMinutes(), 2, '0') + ":"
1996             + pad(date.getSeconds(), 2, '0');
1997     },
1998
1999     
2000     getElapsed: function(dateA, dateB) {
2001         return Math.abs(dateA - (dateB || new Date()));
2002     },
2003
2004     
2005     useStrict: false,
2006
2007     
2008     formatCodeToRegex: function(character, currentGroup) {
2009         
2010         var p = utilDate.parseCodes[character];
2011
2012         if (p) {
2013           p = typeof p == 'function'? p() : p;
2014           utilDate.parseCodes[character] = p; 
2015         }
2016
2017         return p ? Ext.applyIf({
2018           c: p.c ? xf(p.c, currentGroup || "{0}") : p.c
2019         }, p) : {
2020             g: 0,
2021             c: null,
2022             s: Ext.String.escapeRegex(character) 
2023         };
2024     },
2025
2026     
2027     parseFunctions: {
2028         "MS": function(input, strict) {
2029             
2030             
2031             var re = new RegExp('\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/');
2032             var r = (input || '').match(re);
2033             return r? new Date(((r[1] || '') + r[2]) * 1) : null;
2034         }
2035     },
2036     parseRegexes: [],
2037
2038     
2039     formatFunctions: {
2040         "MS": function() {
2041             
2042             return '\\/Date(' + this.getTime() + ')\\/';
2043         }
2044     },
2045
2046     y2kYear : 50,
2047
2048     
2049     MILLI : "ms",
2050
2051     
2052     SECOND : "s",
2053
2054     
2055     MINUTE : "mi",
2056
2057     
2058     HOUR : "h",
2059
2060     
2061     DAY : "d",
2062
2063     
2064     MONTH : "mo",
2065
2066     
2067     YEAR : "y",
2068
2069     
2070     defaults: {},
2071
2072     
2073     dayNames : [
2074         "Sunday",
2075         "Monday",
2076         "Tuesday",
2077         "Wednesday",
2078         "Thursday",
2079         "Friday",
2080         "Saturday"
2081     ],
2082
2083     
2084     monthNames : [
2085         "January",
2086         "February",
2087         "March",
2088         "April",
2089         "May",
2090         "June",
2091         "July",
2092         "August",
2093         "September",
2094         "October",
2095         "November",
2096         "December"
2097     ],
2098
2099     
2100     monthNumbers : {
2101         Jan:0,
2102         Feb:1,
2103         Mar:2,
2104         Apr:3,
2105         May:4,
2106         Jun:5,
2107         Jul:6,
2108         Aug:7,
2109         Sep:8,
2110         Oct:9,
2111         Nov:10,
2112         Dec:11
2113     },
2114     
2115     defaultFormat : "m/d/Y",
2116     
2117     getShortMonthName : function(month) {
2118         return utilDate.monthNames[month].substring(0, 3);
2119     },
2120
2121     
2122     getShortDayName : function(day) {
2123         return utilDate.dayNames[day].substring(0, 3);
2124     },
2125
2126     
2127     getMonthNumber : function(name) {
2128         
2129         return utilDate.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
2130     },
2131
2132     
2133     formatContainsHourInfo : (function(){
2134         var stripEscapeRe = /(\\.)/g,
2135             hourInfoRe = /([gGhHisucUOPZ]|MS)/;
2136         return function(format){
2137             return hourInfoRe.test(format.replace(stripEscapeRe, ''));
2138         };
2139     })(),
2140
2141     
2142     formatContainsDateInfo : (function(){
2143         var stripEscapeRe = /(\\.)/g,
2144             dateInfoRe = /([djzmnYycU]|MS)/;
2145
2146         return function(format){
2147             return dateInfoRe.test(format.replace(stripEscapeRe, ''));
2148         };
2149     })(),
2150
2151     
2152     formatCodes : {
2153         d: "Ext.String.leftPad(this.getDate(), 2, '0')",
2154         D: "Ext.Date.getShortDayName(this.getDay())", 
2155         j: "this.getDate()",
2156         l: "Ext.Date.dayNames[this.getDay()]",
2157         N: "(this.getDay() ? this.getDay() : 7)",
2158         S: "Ext.Date.getSuffix(this)",
2159         w: "this.getDay()",
2160         z: "Ext.Date.getDayOfYear(this)",
2161         W: "Ext.String.leftPad(Ext.Date.getWeekOfYear(this), 2, '0')",
2162         F: "Ext.Date.monthNames[this.getMonth()]",
2163         m: "Ext.String.leftPad(this.getMonth() + 1, 2, '0')",
2164         M: "Ext.Date.getShortMonthName(this.getMonth())", 
2165         n: "(this.getMonth() + 1)",
2166         t: "Ext.Date.getDaysInMonth(this)",
2167         L: "(Ext.Date.isLeapYear(this) ? 1 : 0)",
2168         o: "(this.getFullYear() + (Ext.Date.getWeekOfYear(this) == 1 && this.getMonth() > 0 ? +1 : (Ext.Date.getWeekOfYear(this) >= 52 && this.getMonth() < 11 ? -1 : 0)))",
2169         Y: "Ext.String.leftPad(this.getFullYear(), 4, '0')",
2170         y: "('' + this.getFullYear()).substring(2, 4)",
2171         a: "(this.getHours() < 12 ? 'am' : 'pm')",
2172         A: "(this.getHours() < 12 ? 'AM' : 'PM')",
2173         g: "((this.getHours() % 12) ? this.getHours() % 12 : 12)",
2174         G: "this.getHours()",
2175         h: "Ext.String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')",
2176         H: "Ext.String.leftPad(this.getHours(), 2, '0')",
2177         i: "Ext.String.leftPad(this.getMinutes(), 2, '0')",
2178         s: "Ext.String.leftPad(this.getSeconds(), 2, '0')",
2179         u: "Ext.String.leftPad(this.getMilliseconds(), 3, '0')",
2180         O: "Ext.Date.getGMTOffset(this)",
2181         P: "Ext.Date.getGMTOffset(this, true)",
2182         T: "Ext.Date.getTimezone(this)",
2183         Z: "(this.getTimezoneOffset() * -60)",
2184
2185         c: function() { 
2186             for (var c = "Y-m-dTH:i:sP", code = [], i = 0, l = c.length; i < l; ++i) {
2187                 var e = c.charAt(i);
2188                 code.push(e == "T" ? "'T'" : utilDate.getFormatCode(e)); 
2189             }
2190             return code.join(" + ");
2191         },
2192         
2193
2194         U: "Math.round(this.getTime() / 1000)"
2195     },
2196
2197     
2198     isValid : function(y, m, d, h, i, s, ms) {
2199         
2200         h = h || 0;
2201         i = i || 0;
2202         s = s || 0;
2203         ms = ms || 0;
2204
2205         
2206         var dt = utilDate.add(new Date(y < 100 ? 100 : y, m - 1, d, h, i, s, ms), utilDate.YEAR, y < 100 ? y - 100 : 0);
2207
2208         return y == dt.getFullYear() &&
2209             m == dt.getMonth() + 1 &&
2210             d == dt.getDate() &&
2211             h == dt.getHours() &&
2212             i == dt.getMinutes() &&
2213             s == dt.getSeconds() &&
2214             ms == dt.getMilliseconds();
2215     },
2216
2217     
2218     parse : function(input, format, strict) {
2219         var p = utilDate.parseFunctions;
2220         if (p[format] == null) {
2221             utilDate.createParser(format);
2222         }
2223         return p[format](input, Ext.isDefined(strict) ? strict : utilDate.useStrict);
2224     },
2225
2226     
2227     parseDate: function(input, format, strict){
2228         return utilDate.parse(input, format, strict);
2229     },
2230
2231
2232     
2233     getFormatCode : function(character) {
2234         var f = utilDate.formatCodes[character];
2235
2236         if (f) {
2237           f = typeof f == 'function'? f() : f;
2238           utilDate.formatCodes[character] = f; 
2239         }
2240
2241         
2242         return f || ("'" + Ext.String.escape(character) + "'");
2243     },
2244
2245     
2246     createFormat : function(format) {
2247         var code = [],
2248             special = false,
2249             ch = '';
2250
2251         for (var i = 0; i < format.length; ++i) {
2252             ch = format.charAt(i);
2253             if (!special && ch == "\\") {
2254                 special = true;
2255             } else if (special) {
2256                 special = false;
2257                 code.push("'" + Ext.String.escape(ch) + "'");
2258             } else {
2259                 code.push(utilDate.getFormatCode(ch));
2260             }
2261         }
2262         utilDate.formatFunctions[format] = Ext.functionFactory("return " + code.join('+'));
2263     },
2264
2265     
2266     createParser : (function() {
2267         var code = [
2268             "var dt, y, m, d, h, i, s, ms, o, z, zz, u, v,",
2269                 "def = Ext.Date.defaults,",
2270                 "results = String(input).match(Ext.Date.parseRegexes[{0}]);", 
2271
2272             "if(results){",
2273                 "{1}",
2274
2275                 "if(u != null){", 
2276                     "v = new Date(u * 1000);", 
2277                 "}else{",
2278                     
2279                     
2280                     
2281                     "dt = Ext.Date.clearTime(new Date);",
2282
2283                     
2284                     "y = Ext.Number.from(y, Ext.Number.from(def.y, dt.getFullYear()));",
2285                     "m = Ext.Number.from(m, Ext.Number.from(def.m - 1, dt.getMonth()));",
2286                     "d = Ext.Number.from(d, Ext.Number.from(def.d, dt.getDate()));",
2287
2288                     
2289                     "h  = Ext.Number.from(h, Ext.Number.from(def.h, dt.getHours()));",
2290                     "i  = Ext.Number.from(i, Ext.Number.from(def.i, dt.getMinutes()));",
2291                     "s  = Ext.Number.from(s, Ext.Number.from(def.s, dt.getSeconds()));",
2292                     "ms = Ext.Number.from(ms, Ext.Number.from(def.ms, dt.getMilliseconds()));",
2293
2294                     "if(z >= 0 && y >= 0){",
2295                         
2296                         
2297
2298                         
2299                         
2300                         "v = Ext.Date.add(new Date(y < 100 ? 100 : y, 0, 1, h, i, s, ms), Ext.Date.YEAR, y < 100 ? y - 100 : 0);",
2301
2302                         
2303                         "v = !strict? v : (strict === true && (z <= 364 || (Ext.Date.isLeapYear(v) && z <= 365))? Ext.Date.add(v, Ext.Date.DAY, z) : null);",
2304                     "}else if(strict === true && !Ext.Date.isValid(y, m + 1, d, h, i, s, ms)){", 
2305                         "v = null;", 
2306                     "}else{",
2307                         
2308                         
2309                         "v = Ext.Date.add(new Date(y < 100 ? 100 : y, m, d, h, i, s, ms), Ext.Date.YEAR, y < 100 ? y - 100 : 0);",
2310                     "}",
2311                 "}",
2312             "}",
2313
2314             "if(v){",
2315                 
2316                 "if(zz != null){",
2317                     
2318                     "v = Ext.Date.add(v, Ext.Date.SECOND, -v.getTimezoneOffset() * 60 - zz);",
2319                 "}else if(o){",
2320                     
2321                     "v = Ext.Date.add(v, Ext.Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));",
2322                 "}",
2323             "}",
2324
2325             "return v;"
2326         ].join('\n');
2327
2328         return function(format) {
2329             var regexNum = utilDate.parseRegexes.length,
2330                 currentGroup = 1,
2331                 calc = [],
2332                 regex = [],
2333                 special = false,
2334                 ch = "";
2335
2336             for (var i = 0; i < format.length; ++i) {
2337                 ch = format.charAt(i);
2338                 if (!special && ch == "\\") {
2339                     special = true;
2340                 } else if (special) {
2341                     special = false;
2342                     regex.push(Ext.String.escape(ch));
2343                 } else {
2344                     var obj = utilDate.formatCodeToRegex(ch, currentGroup);
2345                     currentGroup += obj.g;
2346                     regex.push(obj.s);
2347                     if (obj.g && obj.c) {
2348                         calc.push(obj.c);
2349                     }
2350                 }
2351             }
2352
2353             utilDate.parseRegexes[regexNum] = new RegExp("^" + regex.join('') + "$", 'i');
2354             utilDate.parseFunctions[format] = Ext.functionFactory("input", "strict", xf(code, regexNum, calc.join('')));
2355         };
2356     })(),
2357
2358     
2359     parseCodes : {
2360         
2361         d: {
2362             g:1,
2363             c:"d = parseInt(results[{0}], 10);\n",
2364             s:"(\\d{2})" 
2365         },
2366         j: {
2367             g:1,
2368             c:"d = parseInt(results[{0}], 10);\n",
2369             s:"(\\d{1,2})" 
2370         },
2371         D: function() {
2372             for (var a = [], i = 0; i < 7; a.push(utilDate.getShortDayName(i)), ++i); 
2373             return {
2374                 g:0,
2375                 c:null,
2376                 s:"(?:" + a.join("|") +")"
2377             };
2378         },
2379         l: function() {
2380             return {
2381                 g:0,
2382                 c:null,
2383                 s:"(?:" + utilDate.dayNames.join("|") + ")"
2384             };
2385         },
2386         N: {
2387             g:0,
2388             c:null,
2389             s:"[1-7]" 
2390         },
2391         S: {
2392             g:0,
2393             c:null,
2394             s:"(?:st|nd|rd|th)"
2395         },
2396         w: {
2397             g:0,
2398             c:null,
2399             s:"[0-6]" 
2400         },
2401         z: {
2402             g:1,
2403             c:"z = parseInt(results[{0}], 10);\n",
2404             s:"(\\d{1,3})" 
2405         },
2406         W: {
2407             g:0,
2408             c:null,
2409             s:"(?:\\d{2})" 
2410         },
2411         F: function() {
2412             return {
2413                 g:1,
2414                 c:"m = parseInt(Ext.Date.getMonthNumber(results[{0}]), 10);\n", 
2415                 s:"(" + utilDate.monthNames.join("|") + ")"
2416             };
2417         },
2418         M: function() {
2419             for (var a = [], i = 0; i < 12; a.push(utilDate.getShortMonthName(i)), ++i); 
2420             return Ext.applyIf({
2421                 s:"(" + a.join("|") + ")"
2422             }, utilDate.formatCodeToRegex("F"));
2423         },
2424         m: {
2425             g:1,
2426             c:"m = parseInt(results[{0}], 10) - 1;\n",
2427             s:"(\\d{2})" 
2428         },
2429         n: {
2430             g:1,
2431             c:"m = parseInt(results[{0}], 10) - 1;\n",
2432             s:"(\\d{1,2})" 
2433         },
2434         t: {
2435             g:0,
2436             c:null,
2437             s:"(?:\\d{2})" 
2438         },
2439         L: {
2440             g:0,
2441             c:null,
2442             s:"(?:1|0)"
2443         },
2444         o: function() {
2445             return utilDate.formatCodeToRegex("Y");
2446         },
2447         Y: {
2448             g:1,
2449             c:"y = parseInt(results[{0}], 10);\n",
2450             s:"(\\d{4})" 
2451         },
2452         y: {
2453             g:1,
2454             c:"var ty = parseInt(results[{0}], 10);\n"
2455                 + "y = ty > Ext.Date.y2kYear ? 1900 + ty : 2000 + ty;\n", 
2456             s:"(\\d{1,2})"
2457         },
2458         
2459         a: {
2460             g:1,
2461             c:"if (/(am)/i.test(results[{0}])) {\n"
2462                 + "if (!h || h == 12) { h = 0; }\n"
2463                 + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
2464             s:"(am|pm|AM|PM)"
2465         },
2466         A: {
2467             g:1,
2468             c:"if (/(am)/i.test(results[{0}])) {\n"
2469                 + "if (!h || h == 12) { h = 0; }\n"
2470                 + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
2471             s:"(AM|PM|am|pm)"
2472         },
2473         g: function() {
2474             return utilDate.formatCodeToRegex("G");
2475         },
2476         G: {
2477             g:1,
2478             c:"h = parseInt(results[{0}], 10);\n",
2479             s:"(\\d{1,2})" 
2480         },
2481         h: function() {
2482             return utilDate.formatCodeToRegex("H");
2483         },
2484         H: {
2485             g:1,
2486             c:"h = parseInt(results[{0}], 10);\n",
2487             s:"(\\d{2})" 
2488         },
2489         i: {
2490             g:1,
2491             c:"i = parseInt(results[{0}], 10);\n",
2492             s:"(\\d{2})" 
2493         },
2494         s: {
2495             g:1,
2496             c:"s = parseInt(results[{0}], 10);\n",
2497             s:"(\\d{2})" 
2498         },
2499         u: {
2500             g:1,
2501             c:"ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",
2502             s:"(\\d+)" 
2503         },
2504         O: {
2505             g:1,
2506             c:[
2507                 "o = results[{0}];",
2508                 "var sn = o.substring(0,1),", 
2509                     "hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),", 
2510                     "mn = o.substring(3,5) % 60;", 
2511                 "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" 
2512             ].join("\n"),
2513             s: "([+\-]\\d{4})" 
2514         },
2515         P: {
2516             g:1,
2517             c:[
2518                 "o = results[{0}];",
2519                 "var sn = o.substring(0,1),", 
2520                     "hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),", 
2521                     "mn = o.substring(4,6) % 60;", 
2522                 "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" 
2523             ].join("\n"),
2524             s: "([+\-]\\d{2}:\\d{2})" 
2525         },
2526         T: {
2527             g:0,
2528             c:null,
2529             s:"[A-Z]{1,4}" 
2530         },
2531         Z: {
2532             g:1,
2533             c:"zz = results[{0}] * 1;\n" 
2534                   + "zz = (-43200 <= zz && zz <= 50400)? zz : null;\n",
2535             s:"([+\-]?\\d{1,5})" 
2536         },
2537         c: function() {
2538             var calc = [],
2539                 arr = [
2540                     utilDate.formatCodeToRegex("Y", 1), 
2541                     utilDate.formatCodeToRegex("m", 2), 
2542                     utilDate.formatCodeToRegex("d", 3), 
2543                     utilDate.formatCodeToRegex("h", 4), 
2544                     utilDate.formatCodeToRegex("i", 5), 
2545                     utilDate.formatCodeToRegex("s", 6), 
2546                     {c:"ms = results[7] || '0'; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"}, 
2547                     {c:[ 
2548                         "if(results[8]) {", 
2549                             "if(results[8] == 'Z'){",
2550                                 "zz = 0;", 
2551                             "}else if (results[8].indexOf(':') > -1){",
2552                                 utilDate.formatCodeToRegex("P", 8).c, 
2553                             "}else{",
2554                                 utilDate.formatCodeToRegex("O", 8).c, 
2555                             "}",
2556                         "}"
2557                     ].join('\n')}
2558                 ];
2559
2560             for (var i = 0, l = arr.length; i < l; ++i) {
2561                 calc.push(arr[i].c);
2562             }
2563
2564             return {
2565                 g:1,
2566                 c:calc.join(""),
2567                 s:[
2568                     arr[0].s, 
2569                     "(?:", "-", arr[1].s, 
2570                         "(?:", "-", arr[2].s, 
2571                             "(?:",
2572                                 "(?:T| )?", 
2573                                 arr[3].s, ":", arr[4].s,  
2574                                 "(?::", arr[5].s, ")?", 
2575                                 "(?:(?:\\.|,)(\\d+))?", 
2576                                 "(Z|(?:[-+]\\d{2}(?::)?\\d{2}))?", 
2577                             ")?",
2578                         ")?",
2579                     ")?"
2580                 ].join("")
2581             };
2582         },
2583         U: {
2584             g:1,
2585             c:"u = parseInt(results[{0}], 10);\n",
2586             s:"(-?\\d+)" 
2587         }
2588     },
2589
2590     
2591     
2592     dateFormat: function(date, format) {
2593         return utilDate.format(date, format);
2594     },
2595
2596     
2597     format: function(date, format) {
2598         if (utilDate.formatFunctions[format] == null) {
2599             utilDate.createFormat(format);
2600         }
2601         var result = utilDate.formatFunctions[format].call(date);
2602         return result + '';
2603     },
2604
2605     
2606     getTimezone : function(date) {
2607         
2608         
2609         
2610         
2611         
2612         
2613         
2614         
2615         
2616         
2617         
2618         
2619         return date.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, "");
2620     },
2621
2622     
2623     getGMTOffset : function(date, colon) {
2624         var offset = date.getTimezoneOffset();
2625         return (offset > 0 ? "-" : "+")
2626             + Ext.String.leftPad(Math.floor(Math.abs(offset) / 60), 2, "0")
2627             + (colon ? ":" : "")
2628             + Ext.String.leftPad(Math.abs(offset % 60), 2, "0");
2629     },
2630
2631     
2632     getDayOfYear: function(date) {
2633         var num = 0,
2634             d = Ext.Date.clone(date),
2635             m = date.getMonth(),
2636             i;
2637
2638         for (i = 0, d.setDate(1), d.setMonth(0); i < m; d.setMonth(++i)) {
2639             num += utilDate.getDaysInMonth(d);
2640         }
2641         return num + date.getDate() - 1;
2642     },
2643
2644     
2645     getWeekOfYear : (function() {
2646         
2647         var ms1d = 864e5, 
2648             ms7d = 7 * ms1d; 
2649
2650         return function(date) { 
2651             var DC3 = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate() + 3) / ms1d, 
2652                 AWN = Math.floor(DC3 / 7), 
2653                 Wyr = new Date(AWN * ms7d).getUTCFullYear();
2654
2655             return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
2656         };
2657     })(),
2658
2659     
2660     isLeapYear : function(date) {
2661         var year = date.getFullYear();
2662         return !!((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
2663     },
2664
2665     
2666     getFirstDayOfMonth : function(date) {
2667         var day = (date.getDay() - (date.getDate() - 1)) % 7;
2668         return (day < 0) ? (day + 7) : day;
2669     },
2670
2671     
2672     getLastDayOfMonth : function(date) {
2673         return utilDate.getLastDateOfMonth(date).getDay();
2674     },
2675
2676
2677     
2678     getFirstDateOfMonth : function(date) {
2679         return new Date(date.getFullYear(), date.getMonth(), 1);
2680     },
2681
2682     
2683     getLastDateOfMonth : function(date) {
2684         return new Date(date.getFullYear(), date.getMonth(), utilDate.getDaysInMonth(date));
2685     },
2686
2687     
2688     getDaysInMonth: (function() {
2689         var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
2690
2691         return function(date) { 
2692             var m = date.getMonth();
2693
2694             return m == 1 && utilDate.isLeapYear(date) ? 29 : daysInMonth[m];
2695         };
2696     })(),
2697
2698     
2699     getSuffix : function(date) {
2700         switch (date.getDate()) {
2701             case 1:
2702             case 21:
2703             case 31:
2704                 return "st";
2705             case 2:
2706             case 22:
2707                 return "nd";
2708             case 3:
2709             case 23:
2710                 return "rd";
2711             default:
2712                 return "th";
2713         }
2714     },
2715
2716     
2717     clone : function(date) {
2718         return new Date(date.getTime());
2719     },
2720
2721     
2722     isDST : function(date) {
2723         
2724         
2725         return new Date(date.getFullYear(), 0, 1).getTimezoneOffset() != date.getTimezoneOffset();
2726     },
2727
2728     
2729     clearTime : function(date, clone) {
2730         if (clone) {
2731             return Ext.Date.clearTime(Ext.Date.clone(date));
2732         }
2733
2734         
2735         var d = date.getDate();
2736
2737         
2738         date.setHours(0);
2739         date.setMinutes(0);
2740         date.setSeconds(0);
2741         date.setMilliseconds(0);
2742
2743         if (date.getDate() != d) { 
2744             
2745             
2746
2747             
2748             for (var hr = 1, c = utilDate.add(date, Ext.Date.HOUR, hr); c.getDate() != d; hr++, c = utilDate.add(date, Ext.Date.HOUR, hr));
2749
2750             date.setDate(d);
2751             date.setHours(c.getHours());
2752         }
2753
2754         return date;
2755     },
2756
2757     
2758     add : function(date, interval, value) {
2759         var d = Ext.Date.clone(date),
2760             Date = Ext.Date;
2761         if (!interval || value === 0) return d;
2762
2763         switch(interval.toLowerCase()) {
2764             case Ext.Date.MILLI:
2765                 d.setMilliseconds(d.getMilliseconds() + value);
2766                 break;
2767             case Ext.Date.SECOND:
2768                 d.setSeconds(d.getSeconds() + value);
2769                 break;
2770             case Ext.Date.MINUTE:
2771                 d.setMinutes(d.getMinutes() + value);
2772                 break;
2773             case Ext.Date.HOUR:
2774                 d.setHours(d.getHours() + value);
2775                 break;
2776             case Ext.Date.DAY:
2777                 d.setDate(d.getDate() + value);
2778                 break;
2779             case Ext.Date.MONTH:
2780                 var day = date.getDate();
2781                 if (day > 28) {
2782                     day = Math.min(day, Ext.Date.getLastDateOfMonth(Ext.Date.add(Ext.Date.getFirstDateOfMonth(date), 'mo', value)).getDate());
2783                 }
2784                 d.setDate(day);
2785                 d.setMonth(date.getMonth() + value);
2786                 break;
2787             case Ext.Date.YEAR:
2788                 d.setFullYear(date.getFullYear() + value);
2789                 break;
2790         }
2791         return d;
2792     },
2793
2794     
2795     between : function(date, start, end) {
2796         var t = date.getTime();
2797         return start.getTime() <= t && t <= end.getTime();
2798     },
2799
2800     
2801     compat: function() {
2802         var nativeDate = window.Date,
2803             p, u,
2804             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'],
2805             proto = ['dateFormat', 'format', 'getTimezone', 'getGMTOffset', 'getDayOfYear', 'getWeekOfYear', 'isLeapYear', 'getFirstDayOfMonth', 'getLastDayOfMonth', 'getDaysInMonth', 'getSuffix', 'clone', 'isDST', 'clearTime', 'add', 'between'];
2806
2807         
2808         Ext.Array.forEach(statics, function(s) {
2809             nativeDate[s] = utilDate[s];
2810         });
2811
2812         
2813         Ext.Array.forEach(proto, function(s) {
2814             nativeDate.prototype[s] = function() {
2815                 var args = Array.prototype.slice.call(arguments);
2816                 args.unshift(this);
2817                 return utilDate[s].apply(utilDate, args);
2818             };
2819         });
2820     }
2821 };
2822
2823 var utilDate = Ext.Date;
2824
2825 })();
2826
2827
2828 (function(flexSetter) {
2829
2830 var Base = Ext.Base = function() {};
2831     Base.prototype = {
2832         $className: 'Ext.Base',
2833
2834         $class: Base,
2835
2836         
2837         self: Base,
2838
2839         
2840         constructor: function() {
2841             return this;
2842         },
2843
2844         
2845         
2846         initConfig: function(config) {
2847             if (!this.$configInited) {
2848                 this.config = Ext.Object.merge({}, this.config || {}, config || {});
2849
2850                 this.applyConfig(this.config);
2851
2852                 this.$configInited = true;
2853             }
2854
2855             return this;
2856         },
2857
2858         
2859         setConfig: function(config) {
2860             this.applyConfig(config || {});
2861
2862             return this;
2863         },
2864
2865         
2866         applyConfig: flexSetter(function(name, value) {
2867             var setter = 'set' + Ext.String.capitalize(name);
2868
2869             if (typeof this[setter] === 'function') {
2870                 this[setter].call(this, value);
2871             }
2872
2873             return this;
2874         }),
2875         
2876
2877         
2878         callParent: function(args) {
2879             var method = this.callParent.caller,
2880                 parentClass, methodName;
2881
2882             if (!method.$owner) {
2883
2884                 method = method.caller;
2885             }
2886
2887             parentClass = method.$owner.superclass;
2888             methodName = method.$name;
2889
2890
2891             return parentClass[methodName].apply(this, args || []);
2892         },
2893
2894
2895         
2896         statics: function() {
2897             var method = this.statics.caller,
2898                 self = this.self;
2899
2900             if (!method) {
2901                 return self;
2902             }
2903
2904             return method.$owner;
2905         },
2906
2907         
2908         callOverridden: function(args) {
2909             var method = this.callOverridden.caller;
2910
2911
2912             return method.$previous.apply(this, args || []);
2913         },
2914
2915         destroy: function() {}
2916     };
2917
2918     
2919     Ext.apply(Ext.Base, {
2920         
2921         create: function() {
2922             return Ext.create.apply(Ext, [this].concat(Array.prototype.slice.call(arguments, 0)));
2923         },
2924
2925         
2926         own: function(name, value) {
2927             if (typeof value == 'function') {
2928                 this.ownMethod(name, value);
2929             }
2930             else {
2931                 this.prototype[name] = value;
2932             }
2933         },
2934
2935         
2936         ownMethod: function(name, fn) {
2937             var originalFn;
2938
2939             if (typeof fn.$owner !== 'undefined' && fn !== Ext.emptyFn) {
2940                 originalFn = fn;
2941
2942                 fn = function() {
2943                     return originalFn.apply(this, arguments);
2944                 };
2945             }
2946
2947             fn.$owner = this;
2948             fn.$name = name;
2949
2950             this.prototype[name] = fn;
2951         },
2952
2953         
2954         addStatics: function(members) {
2955             for (var name in members) {
2956                 if (members.hasOwnProperty(name)) {
2957                     this[name] = members[name];
2958                 }
2959             }
2960
2961             return this;
2962         },
2963
2964         
2965         addInheritableStatics: function(members) {
2966             var inheritableStatics,
2967                 hasInheritableStatics,
2968                 prototype = this.prototype,
2969                 name, member;
2970
2971             inheritableStatics = prototype.$inheritableStatics;
2972             hasInheritableStatics = prototype.$hasInheritableStatics;
2973
2974             if (!inheritableStatics) {
2975                 inheritableStatics = prototype.$inheritableStatics = [];
2976                 hasInheritableStatics = prototype.$hasInheritableStatics = {};
2977             }
2978
2979
2980             for (name in members) {
2981                 if (members.hasOwnProperty(name)) {
2982                     member = members[name];
2983                     this[name] = member;
2984
2985                     if (!hasInheritableStatics[name]) {
2986                         hasInheritableStatics[name] = true;
2987                         inheritableStatics.push(name);
2988                     }
2989                 }
2990             }
2991
2992             return this;
2993         },
2994
2995         
2996         implement: function(members) {
2997             var prototype = this.prototype,
2998                 enumerables = Ext.enumerables,
2999                 name, i, member;
3000             for (name in members) {
3001                 if (members.hasOwnProperty(name)) {
3002                     member = members[name];
3003
3004                     if (typeof member === 'function') {
3005                         member.$owner = this;
3006                         member.$name = name;
3007                     }
3008
3009                     prototype[name] = member;
3010                 }
3011             }
3012
3013             if (enumerables) {
3014                 for (i = enumerables.length; i--;) {
3015                     name = enumerables[i];
3016
3017                     if (members.hasOwnProperty(name)) {
3018                         member = members[name];
3019                         member.$owner = this;
3020                         member.$name = name;
3021                         prototype[name] = member;
3022                     }
3023                 }
3024             }
3025         },
3026
3027         
3028         borrow: function(fromClass, members) {
3029             var fromPrototype = fromClass.prototype,
3030                 i, ln, member;
3031
3032             members = Ext.Array.from(members);
3033
3034             for (i = 0, ln = members.length; i < ln; i++) {
3035                 member = members[i];
3036
3037                 this.own(member, fromPrototype[member]);
3038             }
3039
3040             return this;
3041         },
3042
3043         
3044         override: function(members) {
3045             var prototype = this.prototype,
3046                 enumerables = Ext.enumerables,
3047                 name, i, member, previous;
3048
3049             if (arguments.length === 2) {
3050                 name = members;
3051                 member = arguments[1];
3052
3053                 if (typeof member == 'function') {
3054                     if (typeof prototype[name] == 'function') {
3055                         previous = prototype[name];
3056                         member.$previous = previous;
3057                     }
3058
3059                     this.ownMethod(name, member);
3060                 }
3061                 else {
3062                     prototype[name] = member;
3063                 }
3064
3065                 return this;
3066             }
3067
3068             for (name in members) {
3069                 if (members.hasOwnProperty(name)) {
3070                     member = members[name];
3071
3072                     if (typeof member === 'function') {
3073                         if (typeof prototype[name] === 'function') {
3074                             previous = prototype[name];
3075                             member.$previous = previous;
3076                         }
3077
3078                         this.ownMethod(name, member);
3079                     }
3080                     else {
3081                         prototype[name] = member;
3082                     }
3083                 }
3084             }
3085
3086             if (enumerables) {
3087                 for (i = enumerables.length; i--;) {
3088                     name = enumerables[i];
3089
3090                     if (members.hasOwnProperty(name)) {
3091                         if (typeof prototype[name] !== 'undefined') {
3092                             previous = prototype[name];
3093                             members[name].$previous = previous;
3094                         }
3095
3096                         this.ownMethod(name, members[name]);
3097                     }
3098                 }
3099             }
3100
3101             return this;
3102         },
3103
3104         
3105         
3106         mixin: function(name, cls) {
3107             var mixin = cls.prototype,
3108                 my = this.prototype,
3109                 key, fn;
3110
3111             for (key in mixin) {
3112                 if (mixin.hasOwnProperty(key)) {
3113                     if (typeof my[key] === 'undefined' && key !== 'mixins' && key !== 'mixinId') {
3114                         if (typeof mixin[key] === 'function') {
3115                             fn = mixin[key];
3116
3117                             if (typeof fn.$owner === 'undefined') {
3118                                 this.ownMethod(key, fn);
3119                             }
3120                             else {
3121                                 my[key] = fn;
3122                             }
3123                         }
3124                         else {
3125                             my[key] = mixin[key];
3126                         }
3127                     }
3128                     
3129                     else if (key === 'config' && my.config && mixin.config) {
3130                         Ext.Object.merge(my.config, mixin.config);
3131                     }
3132                     
3133                 }
3134             }
3135
3136             if (typeof mixin.onClassMixedIn !== 'undefined') {
3137                 mixin.onClassMixedIn.call(cls, this);
3138             }
3139
3140             if (!my.hasOwnProperty('mixins')) {
3141                 if ('mixins' in my) {
3142                     my.mixins = Ext.Object.merge({}, my.mixins);
3143                 }
3144                 else {
3145                     my.mixins = {};
3146                 }
3147             }
3148
3149             my.mixins[name] = mixin;
3150         },
3151         
3152
3153         
3154         getName: function() {
3155             return Ext.getClassName(this);
3156         },
3157
3158         
3159         createAlias: flexSetter(function(alias, origin) {
3160             this.prototype[alias] = function() {
3161                 return this[origin].apply(this, arguments);
3162             }
3163         })
3164     });
3165
3166 })(Ext.Function.flexSetter);
3167
3168
3169 (function() {
3170
3171     var Class,
3172         Base = Ext.Base,
3173         baseStaticProperties = [],
3174         baseStaticProperty;
3175
3176     for (baseStaticProperty in Base) {
3177         if (Base.hasOwnProperty(baseStaticProperty)) {
3178             baseStaticProperties.push(baseStaticProperty);
3179         }
3180     }
3181
3182     
3183     Ext.Class = Class = function(newClass, classData, onClassCreated) {
3184         if (typeof newClass != 'function') {
3185             onClassCreated = classData;
3186             classData = newClass;
3187             newClass = function() {
3188                 return this.constructor.apply(this, arguments);
3189             };
3190         }
3191
3192         if (!classData) {
3193             classData = {};
3194         }
3195
3196         var preprocessorStack = classData.preprocessors || Class.getDefaultPreprocessors(),
3197             registeredPreprocessors = Class.getPreprocessors(),
3198             index = 0,
3199             preprocessors = [],
3200             preprocessor, staticPropertyName, process, i, j, ln;
3201
3202         for (i = 0, ln = baseStaticProperties.length; i < ln; i++) {
3203             staticPropertyName = baseStaticProperties[i];
3204             newClass[staticPropertyName] = Base[staticPropertyName];
3205         }
3206
3207         delete classData.preprocessors;
3208
3209         for (j = 0, ln = preprocessorStack.length; j < ln; j++) {
3210             preprocessor = preprocessorStack[j];
3211
3212             if (typeof preprocessor == 'string') {
3213                 preprocessor = registeredPreprocessors[preprocessor];
3214
3215                 if (!preprocessor.always) {
3216                     if (classData.hasOwnProperty(preprocessor.name)) {
3217                         preprocessors.push(preprocessor.fn);
3218                     }
3219                 }
3220                 else {
3221                     preprocessors.push(preprocessor.fn);
3222                 }
3223             }
3224             else {
3225                 preprocessors.push(preprocessor);
3226             }
3227         }
3228
3229         classData.onClassCreated = onClassCreated || Ext.emptyFn;
3230
3231         classData.onBeforeClassCreated = function(cls, data) {
3232             onClassCreated = data.onClassCreated;
3233
3234             delete data.onBeforeClassCreated;
3235             delete data.onClassCreated;
3236
3237             cls.implement(data);
3238
3239             onClassCreated.call(cls, cls);
3240         };
3241
3242         process = function(cls, data) {
3243             preprocessor = preprocessors[index++];
3244
3245             if (!preprocessor) {
3246                 data.onBeforeClassCreated.apply(this, arguments);
3247                 return;
3248             }
3249
3250             if (preprocessor.call(this, cls, data, process) !== false) {
3251                 process.apply(this, arguments);
3252             }
3253         };
3254
3255         process.call(Class, newClass, classData);
3256
3257         return newClass;
3258     };
3259
3260     Ext.apply(Class, {
3261
3262         
3263         preprocessors: {},
3264
3265         
3266         registerPreprocessor: function(name, fn, always) {
3267             this.preprocessors[name] = {
3268                 name: name,
3269                 always: always ||  false,
3270                 fn: fn
3271             };
3272
3273             return this;
3274         },
3275
3276         
3277         getPreprocessor: function(name) {
3278             return this.preprocessors[name];
3279         },
3280
3281         getPreprocessors: function() {
3282             return this.preprocessors;
3283         },
3284
3285         
3286         getDefaultPreprocessors: function() {
3287             return this.defaultPreprocessors || [];
3288         },
3289
3290         
3291         setDefaultPreprocessors: function(preprocessors) {
3292             this.defaultPreprocessors = Ext.Array.from(preprocessors);
3293
3294             return this;
3295         },
3296
3297         
3298         setDefaultPreprocessorPosition: function(name, offset, relativeName) {
3299             var defaultPreprocessors = this.defaultPreprocessors,
3300                 index;
3301
3302             if (typeof offset == 'string') {
3303                 if (offset === 'first') {
3304                     defaultPreprocessors.unshift(name);
3305
3306                     return this;
3307                 }
3308                 else if (offset === 'last') {
3309                     defaultPreprocessors.push(name);
3310
3311                     return this;
3312                 }
3313
3314                 offset = (offset === 'after') ? 1 : -1;
3315             }
3316
3317             index = Ext.Array.indexOf(defaultPreprocessors, relativeName);
3318
3319             if (index !== -1) {
3320                 Ext.Array.splice(defaultPreprocessors, Math.max(0, index + offset), 0, name);
3321             }
3322
3323             return this;
3324         }
3325     });
3326
3327     
3328     Class.registerPreprocessor('extend', function(cls, data) {
3329         var extend = data.extend,
3330             base = Ext.Base,
3331             basePrototype = base.prototype,
3332             prototype = function() {},
3333             parent, i, k, ln, staticName, parentStatics,
3334             parentPrototype, clsPrototype;
3335
3336         if (extend && extend !== Object) {
3337             parent = extend;
3338         }
3339         else {
3340             parent = base;
3341         }
3342
3343         parentPrototype = parent.prototype;
3344
3345         prototype.prototype = parentPrototype;
3346         clsPrototype = cls.prototype = new prototype();
3347
3348         if (!('$class' in parent)) {
3349             for (i in basePrototype) {
3350                 if (!parentPrototype[i]) {
3351                     parentPrototype[i] = basePrototype[i];
3352                 }
3353             }
3354         }
3355
3356         clsPrototype.self = cls;
3357
3358         cls.superclass = clsPrototype.superclass = parentPrototype;
3359
3360         delete data.extend;
3361
3362         
3363         
3364         parentStatics = parentPrototype.$inheritableStatics;
3365
3366         if (parentStatics) {
3367             for (k = 0, ln = parentStatics.length; k < ln; k++) {
3368                 staticName = parentStatics[k];
3369
3370                 if (!cls.hasOwnProperty(staticName)) {
3371                     cls[staticName] = parent[staticName];
3372                 }
3373             }
3374         }
3375         
3376
3377         
3378         
3379         if (parentPrototype.config) {
3380             clsPrototype.config = Ext.Object.merge({}, parentPrototype.config);
3381         }
3382         else {
3383             clsPrototype.config = {};
3384         }
3385         
3386
3387         
3388         if (clsPrototype.$onExtended) {
3389             clsPrototype.$onExtended.call(cls, cls, data);
3390         }
3391
3392         if (data.onClassExtended) {
3393             clsPrototype.$onExtended = data.onClassExtended;
3394             delete data.onClassExtended;
3395         }
3396         
3397
3398     }, true);
3399
3400     
3401     
3402     Class.registerPreprocessor('statics', function(cls, data) {
3403         cls.addStatics(data.statics);
3404
3405         delete data.statics;
3406     });
3407     
3408
3409     
3410     
3411     Class.registerPreprocessor('inheritableStatics', function(cls, data) {
3412         cls.addInheritableStatics(data.inheritableStatics);
3413
3414         delete data.inheritableStatics;
3415     });
3416     
3417
3418     
3419     
3420     Class.registerPreprocessor('config', function(cls, data) {
3421         var prototype = cls.prototype;
3422
3423         Ext.Object.each(data.config, function(name) {
3424             var cName = name.charAt(0).toUpperCase() + name.substr(1),
3425                 pName = name,
3426                 apply = 'apply' + cName,
3427                 setter = 'set' + cName,
3428                 getter = 'get' + cName;
3429
3430             if (!(apply in prototype) && !data.hasOwnProperty(apply)) {
3431                 data[apply] = function(val) {
3432                     return val;
3433                 };
3434             }
3435
3436             if (!(setter in prototype) && !data.hasOwnProperty(setter)) {
3437                 data[setter] = function(val) {
3438                     var ret = this[apply].call(this, val, this[pName]);
3439
3440                     if (typeof ret != 'undefined') {
3441                         this[pName] = ret;
3442                     }
3443
3444                     return this;
3445                 };
3446             }
3447
3448             if (!(getter in prototype) && !data.hasOwnProperty(getter)) {
3449                 data[getter] = function() {
3450                     return this[pName];
3451                 };
3452             }
3453         });
3454
3455         Ext.Object.merge(prototype.config, data.config);
3456         delete data.config;
3457     });
3458     
3459
3460     
3461     
3462     Class.registerPreprocessor('mixins', function(cls, data) {
3463         var mixins = data.mixins,
3464             name, mixin, i, ln;
3465
3466         delete data.mixins;
3467
3468         Ext.Function.interceptBefore(data, 'onClassCreated', function(cls) {
3469             if (mixins instanceof Array) {
3470                 for (i = 0,ln = mixins.length; i < ln; i++) {
3471                     mixin = mixins[i];
3472                     name = mixin.prototype.mixinId || mixin.$className;
3473
3474                     cls.mixin(name, mixin);
3475                 }
3476             }
3477             else {
3478                 for (name in mixins) {
3479                     if (mixins.hasOwnProperty(name)) {
3480                         cls.mixin(name, mixins[name]);
3481                     }
3482                 }
3483             }
3484         });
3485     });
3486
3487     
3488
3489     Class.setDefaultPreprocessors([
3490         'extend'
3491         
3492         ,'statics'
3493         
3494         
3495         ,'inheritableStatics'
3496         
3497         
3498         ,'config'
3499         
3500         
3501         ,'mixins'
3502         
3503     ]);
3504
3505     
3506     
3507     Ext.extend = function(subclass, superclass, members) {
3508         if (arguments.length === 2 && Ext.isObject(superclass)) {
3509             members = superclass;
3510             superclass = subclass;
3511             subclass = null;
3512         }
3513
3514         var cls;
3515
3516         if (!superclass) {
3517             Ext.Error.raise("Attempting to extend from a class which has not been loaded on the page.");
3518         }
3519
3520         members.extend = superclass;
3521         members.preprocessors = [
3522             'extend'
3523             
3524             ,'statics'
3525             
3526             
3527             ,'inheritableStatics'
3528             
3529             
3530             ,'mixins'
3531             
3532             
3533             ,'config'
3534             
3535         ];
3536
3537         if (subclass) {
3538             cls = new Class(subclass, members);
3539         }
3540         else {
3541             cls = new Class(members);
3542         }
3543
3544         cls.prototype.override = function(o) {
3545             for (var m in o) {
3546                 if (o.hasOwnProperty(m)) {
3547                     this[m] = o[m];
3548                 }
3549             }
3550         };
3551
3552         return cls;
3553     };
3554     
3555
3556 })();
3557
3558
3559 (function(Class, alias) {
3560
3561     var slice = Array.prototype.slice;
3562
3563     var Manager = Ext.ClassManager = {
3564
3565         
3566         classes: {},
3567
3568         
3569         existCache: {},
3570
3571         
3572         namespaceRewrites: [{
3573             from: 'Ext.',
3574             to: Ext
3575         }],
3576
3577         
3578         maps: {
3579             alternateToName: {},
3580             aliasToName: {},
3581             nameToAliases: {}
3582         },
3583
3584         
3585         enableNamespaceParseCache: true,
3586
3587         
3588         namespaceParseCache: {},
3589
3590         
3591         instantiators: [],
3592
3593
3594         
3595         isCreated: function(className) {
3596             var i, ln, part, root, parts;
3597
3598
3599             if (this.classes.hasOwnProperty(className) || this.existCache.hasOwnProperty(className)) {
3600                 return true;
3601             }
3602
3603             root = Ext.global;
3604             parts = this.parseNamespace(className);
3605
3606             for (i = 0, ln = parts.length; i < ln; i++) {
3607                 part = parts[i];
3608
3609                 if (typeof part !== 'string') {
3610                     root = part;
3611                 } else {
3612                     if (!root || !root[part]) {
3613                         return false;
3614                     }
3615
3616                     root = root[part];
3617                 }
3618             }
3619
3620             Ext.Loader.historyPush(className);
3621
3622             this.existCache[className] = true;
3623
3624             return true;
3625         },
3626
3627         
3628         parseNamespace: function(namespace) {
3629
3630             var cache = this.namespaceParseCache;
3631
3632             if (this.enableNamespaceParseCache) {
3633                 if (cache.hasOwnProperty(namespace)) {
3634                     return cache[namespace];
3635                 }
3636             }
3637
3638             var parts = [],
3639                 rewrites = this.namespaceRewrites,
3640                 rewrite, from, to, i, ln, root = Ext.global;
3641
3642             for (i = 0, ln = rewrites.length; i < ln; i++) {
3643                 rewrite = rewrites[i];
3644                 from = rewrite.from;
3645                 to = rewrite.to;
3646
3647                 if (namespace === from || namespace.substring(0, from.length) === from) {
3648                     namespace = namespace.substring(from.length);
3649
3650                     if (typeof to !== 'string') {
3651                         root = to;
3652                     } else {
3653                         parts = parts.concat(to.split('.'));
3654                     }
3655
3656                     break;
3657                 }
3658             }
3659
3660             parts.push(root);
3661
3662             parts = parts.concat(namespace.split('.'));
3663
3664             if (this.enableNamespaceParseCache) {
3665                 cache[namespace] = parts;
3666             }
3667
3668             return parts;
3669         },
3670
3671         
3672         setNamespace: function(name, value) {
3673             var root = Ext.global,
3674                 parts = this.parseNamespace(name),
3675                 ln = parts.length - 1,
3676                 leaf = parts[ln],
3677                 i, part;
3678
3679             for (i = 0; i < ln; i++) {
3680                 part = parts[i];
3681
3682                 if (typeof part !== 'string') {
3683                     root = part;
3684                 } else {
3685                     if (!root[part]) {
3686                         root[part] = {};
3687                     }
3688
3689                     root = root[part];
3690                 }
3691             }
3692
3693             root[leaf] = value;
3694
3695             return root[leaf];
3696         },
3697
3698         
3699         createNamespaces: function() {
3700             var root = Ext.global,
3701                 parts, part, i, j, ln, subLn;
3702
3703             for (i = 0, ln = arguments.length; i < ln; i++) {
3704                 parts = this.parseNamespace(arguments[i]);
3705
3706                 for (j = 0, subLn = parts.length; j < subLn; j++) {
3707                     part = parts[j];
3708
3709                     if (typeof part !== 'string') {
3710                         root = part;
3711                     } else {
3712                         if (!root[part]) {
3713                             root[part] = {};
3714                         }
3715
3716                         root = root[part];
3717                     }
3718                 }
3719             }
3720
3721             return root;
3722         },
3723
3724         
3725         set: function(name, value) {
3726             var targetName = this.getName(value);
3727
3728             this.classes[name] = this.setNamespace(name, value);
3729
3730             if (targetName && targetName !== name) {
3731                 this.maps.alternateToName[name] = targetName;
3732             }
3733
3734             return this;
3735         },
3736
3737         
3738         get: function(name) {
3739             if (this.classes.hasOwnProperty(name)) {
3740                 return this.classes[name];
3741             }
3742
3743             var root = Ext.global,
3744                 parts = this.parseNamespace(name),
3745                 part, i, ln;
3746
3747             for (i = 0, ln = parts.length; i < ln; i++) {
3748                 part = parts[i];
3749
3750                 if (typeof part !== 'string') {
3751                     root = part;
3752                 } else {
3753                     if (!root || !root[part]) {
3754                         return null;
3755                     }
3756
3757                     root = root[part];
3758                 }
3759             }
3760
3761             return root;
3762         },
3763
3764         
3765         setAlias: function(cls, alias) {
3766             var aliasToNameMap = this.maps.aliasToName,
3767                 nameToAliasesMap = this.maps.nameToAliases,
3768                 className;
3769
3770             if (typeof cls === 'string') {
3771                 className = cls;
3772             } else {
3773                 className = this.getName(cls);
3774             }
3775
3776             if (alias && aliasToNameMap[alias] !== className) {
3777
3778                 aliasToNameMap[alias] = className;
3779             }
3780
3781             if (!nameToAliasesMap[className]) {
3782                 nameToAliasesMap[className] = [];
3783             }
3784
3785             if (alias) {
3786                 Ext.Array.include(nameToAliasesMap[className], alias);
3787             }
3788
3789             return this;
3790         },
3791
3792         
3793         getByAlias: function(alias) {
3794             return this.get(this.getNameByAlias(alias));
3795         },
3796
3797         
3798         getNameByAlias: function(alias) {
3799             return this.maps.aliasToName[alias] || '';
3800         },
3801
3802         
3803         getNameByAlternate: function(alternate) {
3804             return this.maps.alternateToName[alternate] || '';
3805         },
3806
3807         
3808         getAliasesByName: function(name) {
3809             return this.maps.nameToAliases[name] || [];
3810         },
3811
3812         
3813         getName: function(object) {
3814             return object && object.$className || '';
3815         },
3816
3817         
3818         getClass: function(object) {
3819             return object && object.self || null;
3820         },
3821
3822         
3823         create: function(className, data, createdFn) {
3824             var manager = this;
3825
3826
3827             data.$className = className;
3828
3829             return new Class(data, function() {
3830                 var postprocessorStack = data.postprocessors || manager.defaultPostprocessors,
3831                     registeredPostprocessors = manager.postprocessors,
3832                     index = 0,
3833                     postprocessors = [],
3834                     postprocessor, process, i, ln;
3835
3836                 delete data.postprocessors;
3837
3838                 for (i = 0, ln = postprocessorStack.length; i < ln; i++) {
3839                     postprocessor = postprocessorStack[i];
3840
3841                     if (typeof postprocessor === 'string') {
3842                         postprocessor = registeredPostprocessors[postprocessor];
3843
3844                         if (!postprocessor.always) {
3845                             if (data[postprocessor.name] !== undefined) {
3846                                 postprocessors.push(postprocessor.fn);
3847                             }
3848                         }
3849                         else {
3850                             postprocessors.push(postprocessor.fn);
3851                         }
3852                     }
3853                     else {
3854                         postprocessors.push(postprocessor);
3855                     }
3856                 }
3857
3858                 process = function(clsName, cls, clsData) {
3859                     postprocessor = postprocessors[index++];
3860
3861                     if (!postprocessor) {
3862                         manager.set(className, cls);
3863
3864                         Ext.Loader.historyPush(className);
3865
3866                         if (createdFn) {
3867                             createdFn.call(cls, cls);
3868                         }
3869
3870                         return;
3871                     }
3872
3873                     if (postprocessor.call(this, clsName, cls, clsData, process) !== false) {
3874                         process.apply(this, arguments);
3875                     }
3876                 };
3877
3878                 process.call(manager, className, this, data);
3879             });
3880         },
3881
3882         
3883         instantiateByAlias: function() {
3884             var alias = arguments[0],
3885                 args = slice.call(arguments),
3886                 className = this.getNameByAlias(alias);
3887
3888             if (!className) {
3889                 className = this.maps.aliasToName[alias];
3890
3891
3892
3893                 Ext.syncRequire(className);
3894             }
3895
3896             args[0] = className;
3897
3898             return this.instantiate.apply(this, args);
3899         },
3900
3901         
3902         instantiate: function() {
3903             var name = arguments[0],
3904                 args = slice.call(arguments, 1),
3905                 alias = name,
3906                 possibleName, cls;
3907
3908             if (typeof name !== 'function') {
3909
3910                 cls = this.get(name);
3911             }
3912             else {
3913                 cls = name;
3914             }
3915
3916             
3917             if (!cls) {
3918                 possibleName = this.getNameByAlias(name);
3919
3920                 if (possibleName) {
3921                     name = possibleName;
3922
3923                     cls = this.get(name);
3924                 }
3925             }
3926
3927             
3928             if (!cls) {
3929                 possibleName = this.getNameByAlternate(name);
3930
3931                 if (possibleName) {
3932                     name = possibleName;
3933
3934                     cls = this.get(name);
3935                 }
3936             }
3937
3938             
3939             if (!cls) {
3940
3941                 Ext.syncRequire(name);
3942
3943                 cls = this.get(name);
3944             }
3945
3946
3947
3948             return this.getInstantiator(args.length)(cls, args);
3949         },
3950
3951         
3952         dynInstantiate: function(name, args) {
3953             args = Ext.Array.from(args, true);
3954             args.unshift(name);
3955
3956             return this.instantiate.apply(this, args);
3957         },
3958
3959         
3960         getInstantiator: function(length) {
3961             if (!this.instantiators[length]) {
3962                 var i = length,
3963                     args = [];
3964
3965                 for (i = 0; i < length; i++) {
3966                     args.push('a['+i+']');
3967                 }
3968
3969                 this.instantiators[length] = new Function('c', 'a', 'return new c('+args.join(',')+')');
3970             }
3971
3972             return this.instantiators[length];
3973         },
3974
3975         
3976         postprocessors: {},
3977
3978         
3979         defaultPostprocessors: [],
3980
3981         
3982         registerPostprocessor: function(name, fn, always) {
3983             this.postprocessors[name] = {
3984                 name: name,
3985                 always: always ||  false,
3986                 fn: fn
3987             };
3988
3989             return this;
3990         },
3991
3992         
3993         setDefaultPostprocessors: function(postprocessors) {
3994             this.defaultPostprocessors = Ext.Array.from(postprocessors);
3995
3996             return this;
3997         },
3998
3999         
4000         setDefaultPostprocessorPosition: function(name, offset, relativeName) {
4001             var defaultPostprocessors = this.defaultPostprocessors,
4002                 index;
4003
4004             if (typeof offset === 'string') {
4005                 if (offset === 'first') {
4006                     defaultPostprocessors.unshift(name);
4007
4008                     return this;
4009                 }
4010                 else if (offset === 'last') {
4011                     defaultPostprocessors.push(name);
4012
4013                     return this;
4014                 }
4015
4016                 offset = (offset === 'after') ? 1 : -1;
4017             }
4018
4019             index = Ext.Array.indexOf(defaultPostprocessors, relativeName);
4020
4021             if (index !== -1) {
4022                 Ext.Array.splice(defaultPostprocessors, Math.max(0, index + offset), 0, name);
4023             }
4024
4025             return this;
4026         },
4027
4028         
4029         getNamesByExpression: function(expression) {
4030             var nameToAliasesMap = this.maps.nameToAliases,
4031                 names = [],
4032                 name, alias, aliases, possibleName, regex, i, ln;
4033
4034
4035             if (expression.indexOf('*') !== -1) {
4036                 expression = expression.replace(/\*/g, '(.*?)');
4037                 regex = new RegExp('^' + expression + '$');
4038
4039                 for (name in nameToAliasesMap) {
4040                     if (nameToAliasesMap.hasOwnProperty(name)) {
4041                         aliases = nameToAliasesMap[name];
4042
4043                         if (name.search(regex) !== -1) {
4044                             names.push(name);
4045                         }
4046                         else {
4047                             for (i = 0, ln = aliases.length; i < ln; i++) {
4048                                 alias = aliases[i];
4049
4050                                 if (alias.search(regex) !== -1) {
4051                                     names.push(name);
4052                                     break;
4053                                 }
4054                             }
4055                         }
4056                     }
4057                 }
4058
4059             } else {
4060                 possibleName = this.getNameByAlias(expression);
4061
4062                 if (possibleName) {
4063                     names.push(possibleName);
4064                 } else {
4065                     possibleName = this.getNameByAlternate(expression);
4066
4067                     if (possibleName) {
4068                         names.push(possibleName);
4069                     } else {
4070                         names.push(expression);
4071                     }
4072                 }
4073             }
4074
4075             return names;
4076         }
4077     };
4078
4079     var defaultPostprocessors = Manager.defaultPostprocessors;
4080     
4081
4082     
4083     Manager.registerPostprocessor('alias', function(name, cls, data) {
4084         var aliases = data.alias,
4085             i, ln;
4086
4087         delete data.alias;
4088
4089         for (i = 0, ln = aliases.length; i < ln; i++) {
4090             alias = aliases[i];
4091
4092             this.setAlias(cls, alias);
4093         }
4094     });
4095
4096     
4097     Manager.registerPostprocessor('singleton', function(name, cls, data, fn) {
4098         fn.call(this, name, new cls(), data);
4099         return false;
4100     });
4101
4102     
4103     Manager.registerPostprocessor('alternateClassName', function(name, cls, data) {
4104         var alternates = data.alternateClassName,
4105             i, ln, alternate;
4106
4107         if (!(alternates instanceof Array)) {
4108             alternates = [alternates];
4109         }
4110
4111         for (i = 0, ln = alternates.length; i < ln; i++) {
4112             alternate = alternates[i];
4113
4114
4115             this.set(alternate, cls);
4116         }
4117     });
4118
4119     Manager.setDefaultPostprocessors(['alias', 'singleton', 'alternateClassName']);
4120
4121     Ext.apply(Ext, {
4122         
4123         create: alias(Manager, 'instantiate'),
4124
4125         
4126         factory: function(item, namespace) {
4127             if (item instanceof Array) {
4128                 var i, ln;
4129
4130                 for (i = 0, ln = item.length; i < ln; i++) {
4131                     item[i] = Ext.factory(item[i], namespace);
4132                 }
4133
4134                 return item;
4135             }
4136
4137             var isString = (typeof item === 'string');
4138
4139             if (isString || (item instanceof Object && item.constructor === Object)) {
4140                 var name, config = {};
4141
4142                 if (isString) {
4143                     name = item;
4144                 }
4145                 else {
4146                     name = item.className;
4147                     config = item;
4148                     delete config.className;
4149                 }
4150
4151                 if (namespace !== undefined && name.indexOf(namespace) === -1) {
4152                     name = namespace + '.' + Ext.String.capitalize(name);
4153                 }
4154
4155                 return Ext.create(name, config);
4156             }
4157
4158             if (typeof item === 'function') {
4159                 return Ext.create(item);
4160             }
4161
4162             return item;
4163         },
4164
4165         
4166         widget: function(name) {
4167             var args = slice.call(arguments);
4168             args[0] = 'widget.' + name;
4169
4170             return Manager.instantiateByAlias.apply(Manager, args);
4171         },
4172
4173         
4174         createByAlias: alias(Manager, 'instantiateByAlias'),
4175
4176         
4177         
4178         
4179         define: function (className, data, createdFn) {
4180             if (!data.override) {
4181                 return Manager.create.apply(Manager, arguments);
4182             }
4183
4184             var requires = data.requires,
4185                 uses = data.uses,
4186                 overrideName = className;
4187
4188             className = data.override;
4189
4190             
4191             data = Ext.apply({}, data);
4192             delete data.requires;
4193             delete data.uses;
4194             delete data.override;
4195
4196             
4197             if (typeof requires == 'string') {
4198                 requires = [ className, requires ];
4199             } else if (requires) {
4200                 requires = requires.slice(0);
4201                 requires.unshift(className);
4202             } else {
4203                 requires = [ className ];
4204             }
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220             return Manager.create(overrideName, {
4221                     requires: requires,
4222                     uses: uses,
4223                     isPartial: true,
4224                     constructor: function () {
4225                     }
4226                 }, function () {
4227                     var cls = Manager.get(className);
4228                     if (cls.override) { 
4229                         cls.override(data);
4230                     } else { 
4231                         cls.self.override(data);
4232                     }
4233
4234                     if (createdFn) {
4235                         
4236                         
4237                         
4238                         createdFn.call(cls);
4239                     }
4240                 });
4241         },
4242
4243         
4244         getClassName: alias(Manager, 'getName'),
4245
4246         
4247         getDisplayName: function(object) {
4248             if (object.displayName) {
4249                 return object.displayName;
4250             }
4251
4252             if (object.$name && object.$class) {
4253                 return Ext.getClassName(object.$class) + '#' + object.$name;
4254             }
4255
4256             if (object.$className) {
4257                 return object.$className;
4258             }
4259
4260             return 'Anonymous';
4261         },
4262
4263         
4264         getClass: alias(Manager, 'getClass'),
4265
4266         
4267         namespace: alias(Manager, 'createNamespaces')
4268     });
4269
4270     
4271     Ext.createWidget = Ext.widget;
4272
4273     
4274     Ext.ns = Ext.namespace;
4275
4276     Class.registerPreprocessor('className', function(cls, data) {
4277         if (data.$className) {
4278             cls.$className = data.$className;
4279         }
4280     }, true);
4281
4282     Class.setDefaultPreprocessorPosition('className', 'first');
4283
4284     Class.registerPreprocessor('xtype', function(cls, data) {
4285         var xtypes = Ext.Array.from(data.xtype),
4286             widgetPrefix = 'widget.',
4287             aliases = Ext.Array.from(data.alias),
4288             i, ln, xtype;
4289
4290         data.xtype = xtypes[0];
4291         data.xtypes = xtypes;
4292
4293         aliases = data.alias = Ext.Array.from(data.alias);
4294
4295         for (i = 0,ln = xtypes.length; i < ln; i++) {
4296             xtype = xtypes[i];
4297
4298
4299             aliases.push(widgetPrefix + xtype);
4300         }
4301
4302         data.alias = aliases;
4303     });
4304
4305     Class.setDefaultPreprocessorPosition('xtype', 'last');
4306
4307     Class.registerPreprocessor('alias', function(cls, data) {
4308         var aliases = Ext.Array.from(data.alias),
4309             xtypes = Ext.Array.from(data.xtypes),
4310             widgetPrefix = 'widget.',
4311             widgetPrefixLength = widgetPrefix.length,
4312             i, ln, alias, xtype;
4313
4314         for (i = 0, ln = aliases.length; i < ln; i++) {
4315             alias = aliases[i];
4316
4317
4318             if (alias.substring(0, widgetPrefixLength) === widgetPrefix) {
4319                 xtype = alias.substring(widgetPrefixLength);
4320                 Ext.Array.include(xtypes, xtype);
4321
4322                 if (!cls.xtype) {
4323                     cls.xtype = data.xtype = xtype;
4324                 }
4325             }
4326         }
4327
4328         data.alias = aliases;
4329         data.xtypes = xtypes;
4330     });
4331
4332     Class.setDefaultPreprocessorPosition('alias', 'last');
4333
4334 })(Ext.Class, Ext.Function.alias);
4335
4336
4337 (function(Manager, Class, flexSetter, alias) {
4338
4339     var
4340         dependencyProperties = ['extend', 'mixins', 'requires'],
4341         Loader;
4342
4343     Loader = Ext.Loader = {
4344         
4345         documentHead: typeof document !== 'undefined' && (document.head || document.getElementsByTagName('head')[0]),
4346
4347         
4348         isLoading: false,
4349
4350         
4351         queue: [],
4352
4353         
4354         isFileLoaded: {},
4355
4356         
4357         readyListeners: [],
4358
4359         
4360         optionalRequires: [],
4361
4362         
4363         requiresMap: {},
4364
4365         
4366         numPendingFiles: 0,
4367
4368         
4369         numLoadedFiles: 0,
4370
4371         
4372         hasFileLoadError: false,
4373
4374         
4375         classNameToFilePathMap: {},
4376
4377         
4378         history: [],
4379
4380         
4381         config: {
4382             
4383             enabled: false,
4384
4385             
4386             disableCaching: true,
4387
4388             
4389             disableCachingParam: '_dc',
4390
4391             
4392             paths: {
4393                 'Ext': '.'
4394             }
4395         },
4396
4397         
4398         setConfig: function(name, value) {
4399             if (Ext.isObject(name) && arguments.length === 1) {
4400                 Ext.Object.merge(this.config, name);
4401             }
4402             else {
4403                 this.config[name] = (Ext.isObject(value)) ? Ext.Object.merge(this.config[name], value) : value;
4404             }
4405
4406             return this;
4407         },
4408
4409         
4410         getConfig: function(name) {
4411             if (name) {
4412                 return this.config[name];
4413             }
4414
4415             return this.config;
4416         },
4417
4418         
4419         setPath: flexSetter(function(name, path) {
4420             this.config.paths[name] = path;
4421
4422             return this;
4423         }),
4424
4425         
4426         getPath: function(className) {
4427             var path = '',
4428                 paths = this.config.paths,
4429                 prefix = this.getPrefix(className);
4430
4431             if (prefix.length > 0) {
4432                 if (prefix === className) {
4433                     return paths[prefix];
4434                 }
4435
4436                 path = paths[prefix];
4437                 className = className.substring(prefix.length + 1);
4438             }
4439
4440             if (path.length > 0) {
4441                 path += '/';
4442             }
4443
4444             return path.replace(/\/\.\//g, '/') + className.replace(/\./g, "/") + '.js';
4445         },
4446
4447         
4448         getPrefix: function(className) {
4449             var paths = this.config.paths,
4450                 prefix, deepestPrefix = '';
4451
4452             if (paths.hasOwnProperty(className)) {
4453                 return className;
4454             }
4455
4456             for (prefix in paths) {
4457                 if (paths.hasOwnProperty(prefix) && prefix + '.' === className.substring(0, prefix.length + 1)) {
4458                     if (prefix.length > deepestPrefix.length) {
4459                         deepestPrefix = prefix;
4460                     }
4461                 }
4462             }
4463
4464             return deepestPrefix;
4465         },
4466
4467         
4468         refreshQueue: function() {
4469             var ln = this.queue.length,
4470                 i, item, j, requires;
4471
4472             if (ln === 0) {
4473                 this.triggerReady();
4474                 return;
4475             }
4476
4477             for (i = 0; i < ln; i++) {
4478                 item = this.queue[i];
4479
4480                 if (item) {
4481                     requires = item.requires;
4482
4483                     
4484                     
4485                     if (requires.length > this.numLoadedFiles) {
4486                         continue;
4487                     }
4488
4489                     j = 0;
4490
4491                     do {
4492                         if (Manager.isCreated(requires[j])) {
4493                             
4494                             Ext.Array.erase(requires, j, 1);
4495                         }
4496                         else {
4497                             j++;
4498                         }
4499                     } while (j < requires.length);
4500
4501                     if (item.requires.length === 0) {
4502                         Ext.Array.erase(this.queue, i, 1);
4503                         item.callback.call(item.scope);
4504                         this.refreshQueue();
4505                         break;
4506                     }
4507                 }
4508             }
4509
4510             return this;
4511         },
4512
4513         
4514         injectScriptElement: function(url, onLoad, onError, scope) {
4515             var script = document.createElement('script'),
4516                 me = this,
4517                 onLoadFn = function() {
4518                     me.cleanupScriptElement(script);
4519                     onLoad.call(scope);
4520                 },
4521                 onErrorFn = function() {
4522                     me.cleanupScriptElement(script);
4523                     onError.call(scope);
4524                 };
4525
4526             script.type = 'text/javascript';
4527             script.src = url;
4528             script.onload = onLoadFn;
4529             script.onerror = onErrorFn;
4530             script.onreadystatechange = function() {
4531                 if (this.readyState === 'loaded' || this.readyState === 'complete') {
4532                     onLoadFn();
4533                 }
4534             };
4535
4536             this.documentHead.appendChild(script);
4537
4538             return script;
4539         },
4540
4541         
4542         cleanupScriptElement: function(script) {
4543             script.onload = null;
4544             script.onreadystatechange = null;
4545             script.onerror = null;
4546
4547             return this;
4548         },
4549
4550         
4551         loadScriptFile: function(url, onLoad, onError, scope, synchronous) {
4552             var me = this,
4553                 noCacheUrl = url + (this.getConfig('disableCaching') ? ('?' + this.getConfig('disableCachingParam') + '=' + Ext.Date.now()) : ''),
4554                 fileName = url.split('/').pop(),
4555                 isCrossOriginRestricted = false,
4556                 xhr, status, onScriptError;
4557
4558             scope = scope || this;
4559
4560             this.isLoading = true;
4561
4562             if (!synchronous) {
4563                 onScriptError = function() {
4564                     onError.call(scope, "Failed loading '" + url + "', please verify that the file exists", synchronous);
4565                 };
4566
4567                 if (!Ext.isReady && Ext.onDocumentReady) {
4568                     Ext.onDocumentReady(function() {
4569                         me.injectScriptElement(noCacheUrl, onLoad, onScriptError, scope);
4570                     });
4571                 }
4572                 else {
4573                     this.injectScriptElement(noCacheUrl, onLoad, onScriptError, scope);
4574                 }
4575             }
4576             else {
4577                 if (typeof XMLHttpRequest !== 'undefined') {
4578                     xhr = new XMLHttpRequest();
4579                 } else {
4580                     xhr = new ActiveXObject('Microsoft.XMLHTTP');
4581                 }
4582
4583                 try {
4584                     xhr.open('GET', noCacheUrl, false);
4585                     xhr.send(null);
4586                 } catch (e) {
4587                     isCrossOriginRestricted = true;
4588                 }
4589
4590                 status = (xhr.status === 1223) ? 204 : xhr.status;
4591
4592                 if (!isCrossOriginRestricted) {
4593                     isCrossOriginRestricted = (status === 0);
4594                 }
4595
4596                 if (isCrossOriginRestricted
4597                 ) {
4598                     onError.call(this, "Failed loading synchronously via XHR: '" + url + "'; It's likely that the file is either " +
4599                                        "being loaded from a different domain or from the local file system whereby cross origin " +
4600                                        "requests are not allowed due to security reasons. Use asynchronous loading with " +
4601                                        "Ext.require instead.", synchronous);
4602                 }
4603                 else if (status >= 200 && status < 300
4604                 ) {
4605                     
4606                     new Function(xhr.responseText + "\n//@ sourceURL=" + fileName)();
4607
4608                     onLoad.call(scope);
4609                 }
4610                 else {
4611                     onError.call(this, "Failed loading synchronously via XHR: '" + url + "'; please " +
4612                                        "verify that the file exists. " +
4613                                        "XHR status code: " + status, synchronous);
4614                 }
4615
4616                 
4617                 xhr = null;
4618             }
4619         },
4620
4621         
4622         exclude: function(excludes) {
4623             var me = this;
4624
4625             return {
4626                 require: function(expressions, fn, scope) {
4627                     return me.require(expressions, fn, scope, excludes);
4628                 },
4629
4630                 syncRequire: function(expressions, fn, scope) {
4631                     return me.syncRequire(expressions, fn, scope, excludes);
4632                 }
4633             };
4634         },
4635
4636         
4637         syncRequire: function() {
4638             this.syncModeEnabled = true;
4639             this.require.apply(this, arguments);
4640             this.refreshQueue();
4641             this.syncModeEnabled = false;
4642         },
4643
4644         
4645         require: function(expressions, fn, scope, excludes) {
4646             var filePath, expression, exclude, className, excluded = {},
4647                 excludedClassNames = [],
4648                 possibleClassNames = [],
4649                 possibleClassName, classNames = [],
4650                 i, j, ln, subLn;
4651
4652             expressions = Ext.Array.from(expressions);
4653             excludes = Ext.Array.from(excludes);
4654
4655             fn = fn || Ext.emptyFn;
4656
4657             scope = scope || Ext.global;
4658
4659             for (i = 0, ln = excludes.length; i < ln; i++) {
4660                 exclude = excludes[i];
4661
4662                 if (typeof exclude === 'string' && exclude.length > 0) {
4663                     excludedClassNames = Manager.getNamesByExpression(exclude);
4664
4665                     for (j = 0, subLn = excludedClassNames.length; j < subLn; j++) {
4666                         excluded[excludedClassNames[j]] = true;
4667                     }
4668                 }
4669             }
4670
4671             for (i = 0, ln = expressions.length; i < ln; i++) {
4672                 expression = expressions[i];
4673
4674                 if (typeof expression === 'string' && expression.length > 0) {
4675                     possibleClassNames = Manager.getNamesByExpression(expression);
4676
4677                     for (j = 0, subLn = possibleClassNames.length; j < subLn; j++) {
4678                         possibleClassName = possibleClassNames[j];
4679
4680                         if (!excluded.hasOwnProperty(possibleClassName) && !Manager.isCreated(possibleClassName)) {
4681                             Ext.Array.include(classNames, possibleClassName);
4682                         }
4683                     }
4684                 }
4685             }
4686
4687             
4688             
4689             if (!this.config.enabled) {
4690                 if (classNames.length > 0) {
4691                     Ext.Error.raise({
4692                         sourceClass: "Ext.Loader",
4693                         sourceMethod: "require",
4694                         msg: "Ext.Loader is not enabled, so dependencies cannot be resolved dynamically. " +
4695                              "Missing required class" + ((classNames.length > 1) ? "es" : "") + ": " + classNames.join(', ')
4696                     });
4697                 }
4698             }
4699
4700             if (classNames.length === 0) {
4701                 fn.call(scope);
4702                 return this;
4703             }
4704
4705             this.queue.push({
4706                 requires: classNames,
4707                 callback: fn,
4708                 scope: scope
4709             });
4710
4711             classNames = classNames.slice();
4712
4713             for (i = 0, ln = classNames.length; i < ln; i++) {
4714                 className = classNames[i];
4715
4716                 if (!this.isFileLoaded.hasOwnProperty(className)) {
4717                     this.isFileLoaded[className] = false;
4718
4719                     filePath = this.getPath(className);
4720
4721                     this.classNameToFilePathMap[className] = filePath;
4722
4723                     this.numPendingFiles++;
4724
4725                     this.loadScriptFile(
4726                         filePath,
4727                         Ext.Function.pass(this.onFileLoaded, [className, filePath], this),
4728                         Ext.Function.pass(this.onFileLoadError, [className, filePath]),
4729                         this,
4730                         this.syncModeEnabled
4731                     );
4732                 }
4733             }
4734
4735             return this;
4736         },
4737
4738         
4739         onFileLoaded: function(className, filePath) {
4740             this.numLoadedFiles++;
4741
4742             this.isFileLoaded[className] = true;
4743
4744             this.numPendingFiles--;
4745
4746             if (this.numPendingFiles === 0) {
4747                 this.refreshQueue();
4748             }
4749
4750
4751         },
4752
4753         
4754         onFileLoadError: function(className, filePath, errorMessage, isSynchronous) {
4755             this.numPendingFiles--;
4756             this.hasFileLoadError = true;
4757
4758         },
4759
4760         
4761         addOptionalRequires: function(requires) {
4762             var optionalRequires = this.optionalRequires,
4763                 i, ln, require;
4764
4765             requires = Ext.Array.from(requires);
4766
4767             for (i = 0, ln = requires.length; i < ln; i++) {
4768                 require = requires[i];
4769
4770                 Ext.Array.include(optionalRequires, require);
4771             }
4772
4773             return this;
4774         },
4775
4776         
4777         triggerReady: function(force) {
4778             var readyListeners = this.readyListeners,
4779                 optionalRequires, listener;
4780
4781             if (this.isLoading || force) {
4782                 this.isLoading = false;
4783
4784                 if (this.optionalRequires.length) {
4785                     
4786                     optionalRequires = Ext.Array.clone(this.optionalRequires);
4787
4788                     
4789                     this.optionalRequires.length = 0;
4790
4791                     this.require(optionalRequires, Ext.Function.pass(this.triggerReady, [true], this), this);
4792                     return this;
4793                 }
4794
4795                 while (readyListeners.length) {
4796                     listener = readyListeners.shift();
4797                     listener.fn.call(listener.scope);
4798
4799                     if (this.isLoading) {
4800                         return this;
4801                     }
4802                 }
4803             }
4804
4805             return this;
4806         },
4807
4808         
4809         onReady: function(fn, scope, withDomReady, options) {
4810             var oldFn;
4811
4812             if (withDomReady !== false && Ext.onDocumentReady) {
4813                 oldFn = fn;
4814
4815                 fn = function() {
4816                     Ext.onDocumentReady(oldFn, scope, options);
4817                 };
4818             }
4819
4820             if (!this.isLoading) {
4821                 fn.call(scope);
4822             }
4823             else {
4824                 this.readyListeners.push({
4825                     fn: fn,
4826                     scope: scope
4827                 });
4828             }
4829         },
4830
4831         
4832         historyPush: function(className) {
4833             if (className && this.isFileLoaded.hasOwnProperty(className)) {
4834                 Ext.Array.include(this.history, className);
4835             }
4836
4837             return this;
4838         }
4839     };
4840
4841     
4842     Ext.require = alias(Loader, 'require');
4843
4844     
4845     Ext.syncRequire = alias(Loader, 'syncRequire');
4846
4847     
4848     Ext.exclude = alias(Loader, 'exclude');
4849
4850     
4851     Ext.onReady = function(fn, scope, options) {
4852         Loader.onReady(fn, scope, true, options);
4853     };
4854
4855     
4856     Class.registerPreprocessor('loader', function(cls, data, continueFn) {
4857         var me = this,
4858             dependencies = [],
4859             className = Manager.getName(cls),
4860             i, j, ln, subLn, value, propertyName, propertyValue;
4861
4862         
4863
4864         for (i = 0, ln = dependencyProperties.length; i < ln; i++) {
4865             propertyName = dependencyProperties[i];
4866
4867             if (data.hasOwnProperty(propertyName)) {
4868                 propertyValue = data[propertyName];
4869
4870                 if (typeof propertyValue === 'string') {
4871                     dependencies.push(propertyValue);
4872                 }
4873                 else if (propertyValue instanceof Array) {
4874                     for (j = 0, subLn = propertyValue.length; j < subLn; j++) {
4875                         value = propertyValue[j];
4876
4877                         if (typeof value === 'string') {
4878                             dependencies.push(value);
4879                         }
4880                     }
4881                 }
4882                 else if (typeof propertyValue != 'function') {
4883                     for (j in propertyValue) {
4884                         if (propertyValue.hasOwnProperty(j)) {
4885                             value = propertyValue[j];
4886
4887                             if (typeof value === 'string') {
4888                                 dependencies.push(value);
4889                             }
4890                         }
4891                     }
4892                 }
4893             }
4894         }
4895
4896         if (dependencies.length === 0) {
4897
4898             return;
4899         }
4900
4901
4902         Loader.require(dependencies, function() {
4903             for (i = 0, ln = dependencyProperties.length; i < ln; i++) {
4904                 propertyName = dependencyProperties[i];
4905
4906                 if (data.hasOwnProperty(propertyName)) {
4907                     propertyValue = data[propertyName];
4908
4909                     if (typeof propertyValue === 'string') {
4910                         data[propertyName] = Manager.get(propertyValue);
4911                     }
4912                     else if (propertyValue instanceof Array) {
4913                         for (j = 0, subLn = propertyValue.length; j < subLn; j++) {
4914                             value = propertyValue[j];
4915
4916                             if (typeof value === 'string') {
4917                                 data[propertyName][j] = Manager.get(value);
4918                             }
4919                         }
4920                     }
4921                     else if (typeof propertyValue != 'function') {
4922                         for (var k in propertyValue) {
4923                             if (propertyValue.hasOwnProperty(k)) {
4924                                 value = propertyValue[k];
4925
4926                                 if (typeof value === 'string') {
4927                                     data[propertyName][k] = Manager.get(value);
4928                                 }
4929                             }
4930                         }
4931                     }
4932                 }
4933             }
4934
4935             continueFn.call(me, cls, data);
4936         });
4937
4938         return false;
4939     }, true);
4940
4941     Class.setDefaultPreprocessorPosition('loader', 'after', 'className');
4942
4943     
4944     Manager.registerPostprocessor('uses', function(name, cls, data) {
4945         var uses = Ext.Array.from(data.uses),
4946             items = [],
4947             i, ln, item;
4948
4949         for (i = 0, ln = uses.length; i < ln; i++) {
4950             item = uses[i];
4951
4952             if (typeof item === 'string') {
4953                 items.push(item);
4954             }
4955         }
4956
4957         Loader.addOptionalRequires(items);
4958     });
4959
4960     Manager.setDefaultPostprocessorPosition('uses', 'last');
4961
4962 })(Ext.ClassManager, Ext.Class, Ext.Function.flexSetter, Ext.Function.alias);
4963
4964
4965 Ext.Error = Ext.extend(Error, {
4966     statics: {
4967         
4968         ignore: false,
4969
4970         
4971         
4972
4973         
4974         raise: function(err){
4975             err = err || {};
4976             if (Ext.isString(err)) {
4977                 err = { msg: err };
4978             }
4979
4980             var method = this.raise.caller;
4981
4982             if (method) {
4983                 if (method.$name) {
4984                     err.sourceMethod = method.$name;
4985                 }
4986                 if (method.$owner) {
4987                     err.sourceClass = method.$owner.$className;
4988                 }
4989             }
4990
4991             if (Ext.Error.handle(err) !== true) {
4992                 var msg = Ext.Error.prototype.toString.call(err);
4993
4994                 Ext.log({
4995                     msg: msg,
4996                     level: 'error',
4997                     dump: err,
4998                     stack: true
4999                 });
5000
5001                 throw new Ext.Error(err);
5002             }
5003         },
5004
5005         
5006         handle: function(){
5007             return Ext.Error.ignore;
5008         }
5009     },
5010
5011     
5012     name: 'Ext.Error',
5013
5014     
5015     constructor: function(config){
5016         if (Ext.isString(config)) {
5017             config = { msg: config };
5018         }
5019
5020         var me = this;
5021
5022         Ext.apply(me, config);
5023
5024         me.message = me.message || me.msg; 
5025         
5026     },
5027
5028     
5029     toString: function(){
5030         var me = this,
5031             className = me.className ? me.className  : '',
5032             methodName = me.methodName ? '.' + me.methodName + '(): ' : '',
5033             msg = me.msg || '(No description provided)';
5034
5035         return className + methodName + msg;
5036     }
5037 });
5038
5039
5040
5041
5042
5043
5044
5045 Ext.JSON = new(function() {
5046     var useHasOwn = !! {}.hasOwnProperty,
5047     isNative = function() {
5048         var useNative = null;
5049
5050         return function() {
5051             if (useNative === null) {
5052                 useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]';
5053             }
5054
5055             return useNative;
5056         };
5057     }(),
5058     pad = function(n) {
5059         return n < 10 ? "0" + n : n;
5060     },
5061     doDecode = function(json) {
5062         return eval("(" + json + ')');
5063     },
5064     doEncode = function(o) {
5065         if (!Ext.isDefined(o) || o === null) {
5066             return "null";
5067         } else if (Ext.isArray(o)) {
5068             return encodeArray(o);
5069         } else if (Ext.isDate(o)) {
5070             return Ext.JSON.encodeDate(o);
5071         } else if (Ext.isString(o)) {
5072             return encodeString(o);
5073         } else if (typeof o == "number") {
5074             
5075             return isFinite(o) ? String(o) : "null";
5076         } else if (Ext.isBoolean(o)) {
5077             return String(o);
5078         } else if (Ext.isObject(o)) {
5079             return encodeObject(o);
5080         } else if (typeof o === "function") {
5081             return "null";
5082         }
5083         return 'undefined';
5084     },
5085     m = {
5086         "\b": '\\b',
5087         "\t": '\\t',
5088         "\n": '\\n',
5089         "\f": '\\f',
5090         "\r": '\\r',
5091         '"': '\\"',
5092         "\\": '\\\\',
5093         '\x0b': '\\u000b' 
5094     },
5095     charToReplace = /[\\\"\x00-\x1f\x7f-\uffff]/g,
5096     encodeString = function(s) {
5097         return '"' + s.replace(charToReplace, function(a) {
5098             var c = m[a];
5099             return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
5100         }) + '"';
5101     },
5102     encodeArray = function(o) {
5103         var a = ["[", ""],
5104         
5105         len = o.length,
5106         i;
5107         for (i = 0; i < len; i += 1) {
5108             a.push(doEncode(o[i]), ',');
5109         }
5110         
5111         a[a.length - 1] = ']';
5112         return a.join("");
5113     },
5114     encodeObject = function(o) {
5115         var a = ["{", ""],
5116         
5117         i;
5118         for (i in o) {
5119             if (!useHasOwn || o.hasOwnProperty(i)) {
5120                 a.push(doEncode(i), ":", doEncode(o[i]), ',');
5121             }
5122         }
5123         
5124         a[a.length - 1] = '}';
5125         return a.join("");
5126     };
5127
5128     
5129     this.encodeDate = function(o) {
5130         return '"' + o.getFullYear() + "-"
5131         + pad(o.getMonth() + 1) + "-"
5132         + pad(o.getDate()) + "T"
5133         + pad(o.getHours()) + ":"
5134         + pad(o.getMinutes()) + ":"
5135         + pad(o.getSeconds()) + '"';
5136     };
5137
5138     
5139     this.encode = function() {
5140         var ec;
5141         return function(o) {
5142             if (!ec) {
5143                 
5144                 ec = isNative() ? JSON.stringify : doEncode;
5145             }
5146             return ec(o);
5147         };
5148     }();
5149
5150
5151     
5152     this.decode = function() {
5153         var dc;
5154         return function(json, safe) {
5155             if (!dc) {
5156                 
5157                 dc = isNative() ? JSON.parse : doDecode;
5158             }
5159             try {
5160                 return dc(json);
5161             } catch (e) {
5162                 if (safe === true) {
5163                     return null;
5164                 }
5165                 Ext.Error.raise({
5166                     sourceClass: "Ext.JSON",
5167                     sourceMethod: "decode",
5168                     msg: "You're trying to decode an invalid JSON String: " + json
5169                 });
5170             }
5171         };
5172     }();
5173
5174 })();
5175
5176 Ext.encode = Ext.JSON.encode;
5177
5178 Ext.decode = Ext.JSON.decode;
5179
5180
5181
5182 Ext.apply(Ext, {
5183     userAgent: navigator.userAgent.toLowerCase(),
5184     cache: {},
5185     idSeed: 1000,
5186     windowId: 'ext-window',
5187     documentId: 'ext-document',
5188
5189     
5190     isReady: false,
5191
5192     
5193     enableGarbageCollector: true,
5194
5195     
5196     enableListenerCollection: true,
5197
5198     
5199     id: function(el, prefix) {
5200         var me = this,
5201             sandboxPrefix = '';
5202         el = Ext.getDom(el, true) || {};
5203         if (el === document) {
5204             el.id = me.documentId;
5205         }
5206         else if (el === window) {
5207             el.id = me.windowId;
5208         }
5209         if (!el.id) {
5210             if (me.isSandboxed) {
5211                 if (!me.uniqueGlobalNamespace) {
5212                     me.getUniqueGlobalNamespace();
5213                 }
5214                 sandboxPrefix = me.uniqueGlobalNamespace + '-';
5215             }
5216             el.id = sandboxPrefix + (prefix || "ext-gen") + (++Ext.idSeed);
5217         }
5218         return el.id;
5219     },
5220
5221     
5222     getBody: function() {
5223         return Ext.get(document.body || false);
5224     },
5225
5226     
5227     getHead: function() {
5228         var head;
5229
5230         return function() {
5231             if (head == undefined) {
5232                 head = Ext.get(document.getElementsByTagName("head")[0]);
5233             }
5234
5235             return head;
5236         };
5237     }(),
5238
5239     
5240     getDoc: function() {
5241         return Ext.get(document);
5242     },
5243
5244     
5245     getCmp: function(id) {
5246         return Ext.ComponentManager.get(id);
5247     },
5248
5249     
5250     getOrientation: function() {
5251         return window.innerHeight > window.innerWidth ? 'portrait' : 'landscape';
5252     },
5253
5254     
5255     destroy: function() {
5256         var ln = arguments.length,
5257         i, arg;
5258
5259         for (i = 0; i < ln; i++) {
5260             arg = arguments[i];
5261             if (arg) {
5262                 if (Ext.isArray(arg)) {
5263                     this.destroy.apply(this, arg);
5264                 }
5265                 else if (Ext.isFunction(arg.destroy)) {
5266                     arg.destroy();
5267                 }
5268                 else if (arg.dom) {
5269                     arg.remove();
5270                 }
5271             }
5272         }
5273     },
5274
5275     
5276     callback: function(callback, scope, args, delay){
5277         if(Ext.isFunction(callback)){
5278             args = args || [];
5279             scope = scope || window;
5280             if (delay) {
5281                 Ext.defer(callback, delay, scope, args);
5282             } else {
5283                 callback.apply(scope, args);
5284             }
5285         }
5286     },
5287
5288     
5289     htmlEncode : function(value) {
5290         return Ext.String.htmlEncode(value);
5291     },
5292
5293     
5294     htmlDecode : function(value) {
5295          return Ext.String.htmlDecode(value);
5296     },
5297
5298     
5299     urlAppend : function(url, s) {
5300         if (!Ext.isEmpty(s)) {
5301             return url + (url.indexOf('?') === -1 ? '?' : '&') + s;
5302         }
5303         return url;
5304     }
5305 });
5306
5307
5308 Ext.ns = Ext.namespace;
5309
5310
5311 window.undefined = window.undefined;
5312
5313
5314 (function(){
5315
5316     var check = function(regex){
5317             return regex.test(Ext.userAgent);
5318         },
5319         isStrict = document.compatMode == "CSS1Compat",
5320         version = function (is, regex) {
5321             var m;
5322             return (is && (m = regex.exec(Ext.userAgent))) ? parseFloat(m[1]) : 0;
5323         },
5324         docMode = document.documentMode,
5325         isOpera = check(/opera/),
5326         isOpera10_5 = isOpera && check(/version\/10\.5/),
5327         isChrome = check(/\bchrome\b/),
5328         isWebKit = check(/webkit/),
5329         isSafari = !isChrome && check(/safari/),
5330         isSafari2 = isSafari && check(/applewebkit\/4/), 
5331         isSafari3 = isSafari && check(/version\/3/),
5332         isSafari4 = isSafari && check(/version\/4/),
5333         isSafari5 = isSafari && check(/version\/5/),
5334         isIE = !isOpera && check(/msie/),
5335         isIE7 = isIE && (check(/msie 7/) || docMode == 7),
5336         isIE8 = isIE && (check(/msie 8/) && docMode != 7 && docMode != 9 || docMode == 8),
5337         isIE9 = isIE && (check(/msie 9/) && docMode != 7 && docMode != 8 || docMode == 9),
5338         isIE6 = isIE && check(/msie 6/),
5339         isGecko = !isWebKit && check(/gecko/),
5340         isGecko3 = isGecko && check(/rv:1\.9/),
5341         isGecko4 = isGecko && check(/rv:2\.0/),
5342         isGecko5 = isGecko && check(/rv:5\./),
5343         isFF3_0 = isGecko3 && check(/rv:1\.9\.0/),
5344         isFF3_5 = isGecko3 && check(/rv:1\.9\.1/),
5345         isFF3_6 = isGecko3 && check(/rv:1\.9\.2/),
5346         isWindows = check(/windows|win32/),
5347         isMac = check(/macintosh|mac os x/),
5348         isLinux = check(/linux/),
5349         scrollbarSize = null,
5350         chromeVersion = version(true, /\bchrome\/(\d+\.\d+)/),
5351         firefoxVersion = version(true, /\bfirefox\/(\d+\.\d+)/),
5352         ieVersion = version(isIE, /msie (\d+\.\d+)/),
5353         operaVersion = version(isOpera, /version\/(\d+\.\d+)/),
5354         safariVersion = version(isSafari, /version\/(\d+\.\d+)/),
5355         webKitVersion = version(isWebKit, /webkit\/(\d+\.\d+)/),
5356         isSecure = /^https/i.test(window.location.protocol);
5357
5358     
5359     try {
5360         document.execCommand("BackgroundImageCache", false, true);
5361     } catch(e) {}
5362
5363
5364     Ext.setVersion('extjs', '4.0.7');
5365     Ext.apply(Ext, {
5366         
5367         SSL_SECURE_URL : isSecure && isIE ? 'javascript:""' : 'about:blank',
5368
5369         
5370
5371         
5372         scopeResetCSS : Ext.buildSettings.scopeResetCSS,
5373
5374         
5375         enableNestedListenerRemoval : false,
5376
5377         
5378         USE_NATIVE_JSON : false,
5379
5380         
5381         getDom : function(el, strict) {
5382             if (!el || !document) {
5383                 return null;
5384             }
5385             if (el.dom) {
5386                 return el.dom;
5387             } else {
5388                 if (typeof el == 'string') {
5389                     var e = document.getElementById(el);
5390                     
5391                     
5392                     if (e && isIE && strict) {
5393                         if (el == e.getAttribute('id')) {
5394                             return e;
5395                         } else {
5396                             return null;
5397                         }
5398                     }
5399                     return e;
5400                 } else {
5401                     return el;
5402                 }
5403             }
5404         },
5405
5406         
5407         removeNode : isIE6 || isIE7 ? function() {
5408             var d;
5409             return function(n){
5410                 if(n && n.tagName != 'BODY'){
5411                     (Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n) : Ext.EventManager.removeAll(n);
5412                     d = d || document.createElement('div');
5413                     d.appendChild(n);
5414                     d.innerHTML = '';
5415                     delete Ext.cache[n.id];
5416                 }
5417             };
5418         }() : function(n) {
5419             if (n && n.parentNode && n.tagName != 'BODY') {
5420                 (Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n) : Ext.EventManager.removeAll(n);
5421                 n.parentNode.removeChild(n);
5422                 delete Ext.cache[n.id];
5423             }
5424         },
5425
5426         isStrict: isStrict,
5427
5428         isIEQuirks: isIE && !isStrict,
5429
5430         
5431         isOpera : isOpera,
5432
5433         
5434         isOpera10_5 : isOpera10_5,
5435
5436         
5437         isWebKit : isWebKit,
5438
5439         
5440         isChrome : isChrome,
5441
5442         
5443         isSafari : isSafari,
5444
5445         
5446         isSafari3 : isSafari3,
5447
5448         
5449         isSafari4 : isSafari4,
5450
5451         
5452         isSafari5 : isSafari5,
5453
5454         
5455         isSafari2 : isSafari2,
5456
5457         
5458         isIE : isIE,
5459
5460         
5461         isIE6 : isIE6,
5462
5463         
5464         isIE7 : isIE7,
5465
5466         
5467         isIE8 : isIE8,
5468
5469         
5470         isIE9 : isIE9,
5471
5472         
5473         isGecko : isGecko,
5474
5475         
5476         isGecko3 : isGecko3,
5477
5478         
5479         isGecko4 : isGecko4,
5480
5481         
5482         isGecko5 : isGecko5,
5483
5484         
5485         isFF3_0 : isFF3_0,
5486
5487         
5488         isFF3_5 : isFF3_5,
5489
5490         
5491         isFF3_6 : isFF3_6,
5492
5493         
5494         isFF4 : 4 <= firefoxVersion && firefoxVersion < 5,
5495
5496         
5497         isFF5 : 5 <= firefoxVersion && firefoxVersion < 6,
5498
5499         
5500         isLinux : isLinux,
5501
5502         
5503         isWindows : isWindows,
5504
5505         
5506         isMac : isMac,
5507
5508         
5509         chromeVersion: chromeVersion,
5510
5511         
5512         firefoxVersion: firefoxVersion,
5513
5514         
5515         ieVersion: ieVersion,
5516
5517         
5518         operaVersion: operaVersion,
5519
5520         
5521         safariVersion: safariVersion,
5522
5523         
5524         webKitVersion: webKitVersion,
5525
5526         
5527         isSecure: isSecure,
5528
5529         
5530         BLANK_IMAGE_URL : (isIE6 || isIE7) ? '/' + '/www.sencha.com/s.gif' : 'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
5531
5532         
5533         value : function(v, defaultValue, allowBlank){
5534             return Ext.isEmpty(v, allowBlank) ? defaultValue : v;
5535         },
5536
5537         
5538         escapeRe : function(s) {
5539             return s.replace(/([-.*+?^${}()|[\]\/\\])/g, "\\$1");
5540         },
5541
5542         
5543         addBehaviors : function(o){
5544             if(!Ext.isReady){
5545                 Ext.onReady(function(){
5546                     Ext.addBehaviors(o);
5547                 });
5548             } else {
5549                 var cache = {}, 
5550                     parts,
5551                     b,
5552                     s;
5553                 for (b in o) {
5554                     if ((parts = b.split('@'))[1]) { 
5555                         s = parts[0];
5556                         if(!cache[s]){
5557                             cache[s] = Ext.select(s);
5558                         }
5559                         cache[s].on(parts[1], o[b]);
5560                     }
5561                 }
5562                 cache = null;
5563             }
5564         },
5565
5566         
5567         getScrollbarSize: function (force) {
5568             if(!Ext.isReady){
5569                 return 0;
5570             }
5571
5572             if(force === true || scrollbarSize === null){
5573                 
5574                 
5575                 
5576                 var cssClass = Ext.isIE9 ? '' : Ext.baseCSSPrefix + 'hide-offsets',
5577                     
5578                     div = Ext.getBody().createChild('<div class="' + cssClass + '" style="width:100px;height:50px;overflow:hidden;"><div style="height:200px;"></div></div>'),
5579                     child = div.child('div', true),
5580                     w1 = child.offsetWidth;
5581
5582                 div.setStyle('overflow', (Ext.isWebKit || Ext.isGecko) ? 'auto' : 'scroll');
5583
5584                 var w2 = child.offsetWidth, width = w1 - w2;
5585                 div.remove();
5586
5587                 
5588                 scrollbarSize = { width: width, height: width };
5589             }
5590
5591             return scrollbarSize;
5592         },
5593
5594         
5595         getScrollBarWidth: function(force){
5596             var size = Ext.getScrollbarSize(force);
5597             return size.width + 2; 
5598         },
5599
5600         
5601         copyTo : function(dest, source, names, usePrototypeKeys){
5602             if(typeof names == 'string'){
5603                 names = names.split(/[,;\s]/);
5604             }
5605             Ext.each(names, function(name){
5606                 if(usePrototypeKeys || source.hasOwnProperty(name)){
5607                     dest[name] = source[name];
5608                 }
5609             }, this);
5610             return dest;
5611         },
5612
5613         
5614         destroyMembers : function(o){
5615             for (var i = 1, a = arguments, len = a.length; i < len; i++) {
5616                 Ext.destroy(o[a[i]]);
5617                 delete o[a[i]];
5618             }
5619         },
5620
5621         
5622         log :
5623             Ext.emptyFn,
5624
5625         
5626         partition : function(arr, truth){
5627             var ret = [[],[]];
5628             Ext.each(arr, function(v, i, a) {
5629                 ret[ (truth && truth(v, i, a)) || (!truth && v) ? 0 : 1].push(v);
5630             });
5631             return ret;
5632         },
5633
5634         
5635         invoke : function(arr, methodName){
5636             var ret = [],
5637                 args = Array.prototype.slice.call(arguments, 2);
5638             Ext.each(arr, function(v,i) {
5639                 if (v && typeof v[methodName] == 'function') {
5640                     ret.push(v[methodName].apply(v, args));
5641                 } else {
5642                     ret.push(undefined);
5643                 }
5644             });
5645             return ret;
5646         },
5647
5648         
5649         zip : function(){
5650             var parts = Ext.partition(arguments, function( val ){ return typeof val != 'function'; }),
5651                 arrs = parts[0],
5652                 fn = parts[1][0],
5653                 len = Ext.max(Ext.pluck(arrs, "length")),
5654                 ret = [];
5655
5656             for (var i = 0; i < len; i++) {
5657                 ret[i] = [];
5658                 if(fn){
5659                     ret[i] = fn.apply(fn, Ext.pluck(arrs, i));
5660                 }else{
5661                     for (var j = 0, aLen = arrs.length; j < aLen; j++){
5662                         ret[i].push( arrs[j][i] );
5663                     }
5664                 }
5665             }
5666             return ret;
5667         },
5668
5669         
5670         toSentence: function(items, connector) {
5671             var length = items.length;
5672
5673             if (length <= 1) {
5674                 return items[0];
5675             } else {
5676                 var head = items.slice(0, length - 1),
5677                     tail = items[length - 1];
5678
5679                 return Ext.util.Format.format("{0} {1} {2}", head.join(", "), connector || 'and', tail);
5680             }
5681         },
5682
5683         
5684         useShims: isIE6
5685     });
5686 })();
5687
5688
5689 Ext.application = function(config) {
5690     Ext.require('Ext.app.Application');
5691
5692     Ext.onReady(function() {
5693         Ext.create('Ext.app.Application', config);
5694     });
5695 };
5696
5697
5698 (function() {
5699     Ext.ns('Ext.util');
5700
5701     Ext.util.Format = {};
5702     var UtilFormat     = Ext.util.Format,
5703         stripTagsRE    = /<\/?[^>]+>/gi,
5704         stripScriptsRe = /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,
5705         nl2brRe        = /\r?\n/g,
5706
5707         
5708         formatCleanRe  = /[^\d\.]/g,
5709
5710         
5711         
5712         I18NFormatCleanRe;
5713
5714     Ext.apply(UtilFormat, {
5715         
5716         thousandSeparator: ',',
5717
5718         
5719         decimalSeparator: '.',
5720
5721         
5722         currencyPrecision: 2,
5723
5724         
5725         currencySign: '$',
5726
5727         
5728         currencyAtEnd: false,
5729
5730         
5731         undef : function(value) {
5732             return value !== undefined ? value : "";
5733         },
5734
5735         
5736         defaultValue : function(value, defaultValue) {
5737             return value !== undefined && value !== '' ? value : defaultValue;
5738         },
5739
5740         
5741         substr : function(value, start, length) {
5742             return String(value).substr(start, length);
5743         },
5744
5745         
5746         lowercase : function(value) {
5747             return String(value).toLowerCase();
5748         },
5749
5750         
5751         uppercase : function(value) {
5752             return String(value).toUpperCase();
5753         },
5754
5755         
5756         usMoney : function(v) {
5757             return UtilFormat.currency(v, '$', 2);
5758         },
5759
5760         
5761         currency: function(v, currencySign, decimals, end) {
5762             var negativeSign = '',
5763                 format = ",0",
5764                 i = 0;
5765             v = v - 0;
5766             if (v < 0) {
5767                 v = -v;
5768                 negativeSign = '-';
5769             }
5770             decimals = decimals || UtilFormat.currencyPrecision;
5771             format += format + (decimals > 0 ? '.' : '');
5772             for (; i < decimals; i++) {
5773                 format += '0';
5774             }
5775             v = UtilFormat.number(v, format);
5776             if ((end || UtilFormat.currencyAtEnd) === true) {
5777                 return Ext.String.format("{0}{1}{2}", negativeSign, v, currencySign || UtilFormat.currencySign);
5778             } else {
5779                 return Ext.String.format("{0}{1}{2}", negativeSign, currencySign || UtilFormat.currencySign, v);
5780             }
5781         },
5782
5783         
5784         date: function(v, format) {
5785             if (!v) {
5786                 return "";
5787             }
5788             if (!Ext.isDate(v)) {
5789                 v = new Date(Date.parse(v));
5790             }
5791             return Ext.Date.dateFormat(v, format || Ext.Date.defaultFormat);
5792         },
5793
5794         
5795         dateRenderer : function(format) {
5796             return function(v) {
5797                 return UtilFormat.date(v, format);
5798             };
5799         },
5800
5801         
5802         stripTags : function(v) {
5803             return !v ? v : String(v).replace(stripTagsRE, "");
5804         },
5805
5806         
5807         stripScripts : function(v) {
5808             return !v ? v : String(v).replace(stripScriptsRe, "");
5809         },
5810
5811         
5812         fileSize : function(size) {
5813             if (size < 1024) {
5814                 return size + " bytes";
5815             } else if (size < 1048576) {
5816                 return (Math.round(((size*10) / 1024))/10) + " KB";
5817             } else {
5818                 return (Math.round(((size*10) / 1048576))/10) + " MB";
5819             }
5820         },
5821
5822         
5823         math : function(){
5824             var fns = {};
5825
5826             return function(v, a){
5827                 if (!fns[a]) {
5828                     fns[a] = Ext.functionFactory('v', 'return v ' + a + ';');
5829                 }
5830                 return fns[a](v);
5831             };
5832         }(),
5833
5834         
5835         round : function(value, precision) {
5836             var result = Number(value);
5837             if (typeof precision == 'number') {
5838                 precision = Math.pow(10, precision);
5839                 result = Math.round(value * precision) / precision;
5840             }
5841             return result;
5842         },
5843
5844         
5845         number: function(v, formatString) {
5846             if (!formatString) {
5847                 return v;
5848             }
5849             v = Ext.Number.from(v, NaN);
5850             if (isNaN(v)) {
5851                 return '';
5852             }
5853             var comma = UtilFormat.thousandSeparator,
5854                 dec   = UtilFormat.decimalSeparator,
5855                 i18n  = false,
5856                 neg   = v < 0,
5857                 hasComma,
5858                 psplit;
5859
5860             v = Math.abs(v);
5861
5862             
5863             
5864             
5865             
5866             if (formatString.substr(formatString.length - 2) == '/i') {
5867                 if (!I18NFormatCleanRe) {
5868                     I18NFormatCleanRe = new RegExp('[^\\d\\' + UtilFormat.decimalSeparator + ']','g');
5869                 }
5870                 formatString = formatString.substr(0, formatString.length - 2);
5871                 i18n   = true;
5872                 hasComma = formatString.indexOf(comma) != -1;
5873                 psplit = formatString.replace(I18NFormatCleanRe, '').split(dec);
5874             } else {
5875                 hasComma = formatString.indexOf(',') != -1;
5876                 psplit = formatString.replace(formatCleanRe, '').split('.');
5877             }
5878
5879             if (1 < psplit.length) {
5880                 v = v.toFixed(psplit[1].length);
5881             } else if(2 < psplit.length) {
5882             } else {
5883                 v = v.toFixed(0);
5884             }
5885
5886             var fnum = v.toString();
5887
5888             psplit = fnum.split('.');
5889
5890             if (hasComma) {
5891                 var cnum = psplit[0],
5892                     parr = [],
5893                     j    = cnum.length,
5894                     m    = Math.floor(j / 3),
5895                     n    = cnum.length % 3 || 3,
5896                     i;
5897
5898                 for (i = 0; i < j; i += n) {
5899                     if (i !== 0) {
5900                         n = 3;
5901                     }
5902
5903                     parr[parr.length] = cnum.substr(i, n);
5904                     m -= 1;
5905                 }
5906                 fnum = parr.join(comma);
5907                 if (psplit[1]) {
5908                     fnum += dec + psplit[1];
5909                 }
5910             } else {
5911                 if (psplit[1]) {
5912                     fnum = psplit[0] + dec + psplit[1];
5913                 }
5914             }
5915
5916             if (neg) {
5917                 
5918                 neg = fnum.replace(/[^1-9]/g, '') !== '';
5919             }
5920
5921             return (neg ? '-' : '') + formatString.replace(/[\d,?\.?]+/, fnum);
5922         },
5923
5924         
5925         numberRenderer : function(format) {
5926             return function(v) {
5927                 return UtilFormat.number(v, format);
5928             };
5929         },
5930
5931         
5932         plural : function(v, s, p) {
5933             return v +' ' + (v == 1 ? s : (p ? p : s+'s'));
5934         },
5935
5936         
5937         nl2br : function(v) {
5938             return Ext.isEmpty(v) ? '' : v.replace(nl2brRe, '<br/>');
5939         },
5940
5941         
5942         capitalize: Ext.String.capitalize,
5943
5944         
5945         ellipsis: Ext.String.ellipsis,
5946
5947         
5948         format: Ext.String.format,
5949
5950         
5951         htmlDecode: Ext.String.htmlDecode,
5952
5953         
5954         htmlEncode: Ext.String.htmlEncode,
5955
5956         
5957         leftPad: Ext.String.leftPad,
5958
5959         
5960         trim : Ext.String.trim,
5961
5962         
5963         parseBox : function(box) {
5964             if (Ext.isNumber(box)) {
5965                 box = box.toString();
5966             }
5967             var parts  = box.split(' '),
5968                 ln = parts.length;
5969
5970             if (ln == 1) {
5971                 parts[1] = parts[2] = parts[3] = parts[0];
5972             }
5973             else if (ln == 2) {
5974                 parts[2] = parts[0];
5975                 parts[3] = parts[1];
5976             }
5977             else if (ln == 3) {
5978                 parts[3] = parts[1];
5979             }
5980
5981             return {
5982                 top   :parseInt(parts[0], 10) || 0,
5983                 right :parseInt(parts[1], 10) || 0,
5984                 bottom:parseInt(parts[2], 10) || 0,
5985                 left  :parseInt(parts[3], 10) || 0
5986             };
5987         },
5988
5989         
5990         escapeRegex : function(s) {
5991             return s.replace(/([\-.*+?\^${}()|\[\]\/\\])/g, "\\$1");
5992         }
5993     });
5994 })();
5995
5996
5997 Ext.ns('Ext.util');
5998
5999 Ext.util.TaskRunner = function(interval) {
6000     interval = interval || 10;
6001     var tasks = [],
6002     removeQueue = [],
6003     id = 0,
6004     running = false,
6005
6006     
6007     stopThread = function() {
6008         running = false;
6009         clearInterval(id);
6010         id = 0;
6011     },
6012
6013     
6014     startThread = function() {
6015         if (!running) {
6016             running = true;
6017             id = setInterval(runTasks, interval);
6018         }
6019     },
6020
6021     
6022     removeTask = function(t) {
6023         removeQueue.push(t);
6024         if (t.onStop) {
6025             t.onStop.apply(t.scope || t);
6026         }
6027     },
6028
6029     
6030     runTasks = function() {
6031         var rqLen = removeQueue.length,
6032             now = new Date().getTime(),
6033             i;
6034
6035         if (rqLen > 0) {
6036             for (i = 0; i < rqLen; i++) {
6037                 Ext.Array.remove(tasks, removeQueue[i]);
6038             }
6039             removeQueue = [];
6040             if (tasks.length < 1) {
6041                 stopThread();
6042                 return;
6043             }
6044         }
6045         i = 0;
6046         var t,
6047             itime,
6048             rt,
6049             len = tasks.length;
6050         for (; i < len; ++i) {
6051             t = tasks[i];
6052             itime = now - t.taskRunTime;
6053             if (t.interval <= itime) {
6054                 rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
6055                 t.taskRunTime = now;
6056                 if (rt === false || t.taskRunCount === t.repeat) {
6057                     removeTask(t);
6058                     return;
6059                 }
6060             }
6061             if (t.duration && t.duration <= (now - t.taskStartTime)) {
6062                 removeTask(t);
6063             }
6064         }
6065     };
6066
6067     
6068     this.start = function(task) {
6069         tasks.push(task);
6070         task.taskStartTime = new Date().getTime();
6071         task.taskRunTime = 0;
6072         task.taskRunCount = 0;
6073         startThread();
6074         return task;
6075     };
6076
6077     
6078     this.stop = function(task) {
6079         removeTask(task);
6080         return task;
6081     };
6082
6083     
6084     this.stopAll = function() {
6085         stopThread();
6086         for (var i = 0, len = tasks.length; i < len; i++) {
6087             if (tasks[i].onStop) {
6088                 tasks[i].onStop();
6089             }
6090         }
6091         tasks = [];
6092         removeQueue = [];
6093     };
6094 };
6095
6096
6097 Ext.TaskManager = Ext.create('Ext.util.TaskRunner');
6098
6099 Ext.is = {
6100     init : function(navigator) {
6101         var platforms = this.platforms,
6102             ln = platforms.length,
6103             i, platform;
6104
6105         navigator = navigator || window.navigator;
6106
6107         for (i = 0; i < ln; i++) {
6108             platform = platforms[i];
6109             this[platform.identity] = platform.regex.test(navigator[platform.property]);
6110         }
6111
6112         
6113         this.Desktop = this.Mac || this.Windows || (this.Linux && !this.Android);
6114         
6115         this.Tablet = this.iPad;
6116         
6117         this.Phone = !this.Desktop && !this.Tablet;
6118         
6119         this.iOS = this.iPhone || this.iPad || this.iPod;
6120         
6121         
6122         this.Standalone = !!window.navigator.standalone;
6123     },
6124     
6125     
6126     platforms: [{
6127         property: 'platform',
6128         regex: /iPhone/i,
6129         identity: 'iPhone'
6130     },
6131     
6132     
6133     {
6134         property: 'platform',
6135         regex: /iPod/i,
6136         identity: 'iPod'
6137     },
6138     
6139     
6140     {
6141         property: 'userAgent',
6142         regex: /iPad/i,
6143         identity: 'iPad'
6144     },
6145     
6146     
6147     {
6148         property: 'userAgent',
6149         regex: /Blackberry/i,
6150         identity: 'Blackberry'
6151     },
6152     
6153     
6154     {
6155         property: 'userAgent',
6156         regex: /Android/i,
6157         identity: 'Android'
6158     },
6159     
6160     
6161     {
6162         property: 'platform',
6163         regex: /Mac/i,
6164         identity: 'Mac'
6165     },
6166     
6167     
6168     {
6169         property: 'platform',
6170         regex: /Win/i,
6171         identity: 'Windows'
6172     },
6173     
6174     
6175     {
6176         property: 'platform',
6177         regex: /Linux/i,
6178         identity: 'Linux'
6179     }]
6180 };
6181
6182 Ext.is.init();
6183
6184
6185 Ext.supports = {
6186     init : function() {
6187         var doc = document,
6188             div = doc.createElement('div'),
6189             tests = this.tests,
6190             ln = tests.length,
6191             i, test;
6192
6193         div.innerHTML = [
6194             '<div style="height:30px;width:50px;">',
6195                 '<div style="height:20px;width:20px;"></div>',
6196             '</div>',
6197             '<div style="width: 200px; height: 200px; position: relative; padding: 5px;">',
6198                 '<div style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></div>',
6199             '</div>',
6200             '<div style="float:left; background-color:transparent;"></div>'
6201         ].join('');
6202
6203         doc.body.appendChild(div);
6204
6205         for (i = 0; i < ln; i++) {
6206             test = tests[i];
6207             this[test.identity] = test.fn.call(this, doc, div);
6208         }
6209
6210         doc.body.removeChild(div);
6211     },
6212
6213     
6214     CSS3BoxShadow: Ext.isDefined(document.documentElement.style.boxShadow),
6215
6216     
6217     ClassList: !!document.documentElement.classList,
6218
6219     
6220     OrientationChange: ((typeof window.orientation != 'undefined') && ('onorientationchange' in window)),
6221     
6222     
6223     DeviceMotion: ('ondevicemotion' in window),
6224     
6225     
6226     
6227     
6228     Touch: ('ontouchstart' in window) && (!Ext.is.Desktop),
6229
6230     tests: [
6231         
6232         {
6233             identity: 'Transitions',
6234             fn: function(doc, div) {
6235                 var prefix = [
6236                         'webkit',
6237                         'Moz',
6238                         'o',
6239                         'ms',
6240                         'khtml'
6241                     ],
6242                     TE = 'TransitionEnd',
6243                     transitionEndName = [
6244                         prefix[0] + TE,
6245                         'transitionend', 
6246                         prefix[2] + TE,
6247                         prefix[3] + TE,
6248                         prefix[4] + TE
6249                     ],
6250                     ln = prefix.length,
6251                     i = 0,
6252                     out = false;
6253                 div = Ext.get(div);
6254                 for (; i < ln; i++) {
6255                     if (div.getStyle(prefix[i] + "TransitionProperty")) {
6256                         Ext.supports.CSS3Prefix = prefix[i];
6257                         Ext.supports.CSS3TransitionEnd = transitionEndName[i];
6258                         out = true;
6259                         break;
6260                     }
6261                 }
6262                 return out;
6263             }
6264         },
6265         
6266         
6267         {
6268             identity: 'RightMargin',
6269             fn: function(doc, div) {
6270                 var view = doc.defaultView;
6271                 return !(view && view.getComputedStyle(div.firstChild.firstChild, null).marginRight != '0px');
6272             }
6273         },
6274
6275         
6276         {
6277             identity: 'DisplayChangeInputSelectionBug',
6278             fn: function() {
6279                 var webKitVersion = Ext.webKitVersion;
6280                 
6281                 return 0 < webKitVersion && webKitVersion < 533;
6282             }
6283         },
6284
6285         
6286         {
6287             identity: 'DisplayChangeTextAreaSelectionBug',
6288             fn: function() {
6289                 var webKitVersion = Ext.webKitVersion;
6290
6291                 
6292                 return 0 < webKitVersion && webKitVersion < 534.24;
6293             }
6294         },
6295
6296         
6297         {
6298             identity: 'TransparentColor',
6299             fn: function(doc, div, view) {
6300                 view = doc.defaultView;
6301                 return !(view && view.getComputedStyle(div.lastChild, null).backgroundColor != 'transparent');
6302             }
6303         },
6304
6305         
6306         {
6307             identity: 'ComputedStyle',
6308             fn: function(doc, div, view) {
6309                 view = doc.defaultView;
6310                 return view && view.getComputedStyle;
6311             }
6312         },
6313         
6314         
6315         {
6316             identity: 'Svg',
6317             fn: function(doc) {
6318                 return !!doc.createElementNS && !!doc.createElementNS( "http:/" + "/www.w3.org/2000/svg", "svg").createSVGRect;
6319             }
6320         },
6321     
6322         
6323         {
6324             identity: 'Canvas',
6325             fn: function(doc) {
6326                 return !!doc.createElement('canvas').getContext;
6327             }
6328         },
6329         
6330         
6331         {
6332             identity: 'Vml',
6333             fn: function(doc) {
6334                 var d = doc.createElement("div");
6335                 d.innerHTML = "<!--[if vml]><br><br><![endif]-->";
6336                 return (d.childNodes.length == 2);
6337             }
6338         },
6339         
6340         
6341         {
6342             identity: 'Float',
6343             fn: function(doc, div) {
6344                 return !!div.lastChild.style.cssFloat;
6345             }
6346         },
6347         
6348         
6349         {
6350             identity: 'AudioTag',
6351             fn: function(doc) {
6352                 return !!doc.createElement('audio').canPlayType;
6353             }
6354         },
6355         
6356         
6357         {
6358             identity: 'History',
6359             fn: function() {
6360                 return !!(window.history && history.pushState);
6361             }
6362         },
6363         
6364         
6365         {
6366             identity: 'CSS3DTransform',
6367             fn: function() {
6368                 return (typeof WebKitCSSMatrix != 'undefined' && new WebKitCSSMatrix().hasOwnProperty('m41'));
6369             }
6370         },
6371
6372                 
6373         {
6374             identity: 'CSS3LinearGradient',
6375             fn: function(doc, div) {
6376                 var property = 'background-image:',
6377                     webkit   = '-webkit-gradient(linear, left top, right bottom, from(black), to(white))',
6378                     w3c      = 'linear-gradient(left top, black, white)',
6379                     moz      = '-moz-' + w3c,
6380                     options  = [property + webkit, property + w3c, property + moz];
6381                 
6382                 div.style.cssText = options.join(';');
6383                 
6384                 return ("" + div.style.backgroundImage).indexOf('gradient') !== -1;
6385             }
6386         },
6387         
6388         
6389         {
6390             identity: 'CSS3BorderRadius',
6391             fn: function(doc, div) {
6392                 var domPrefixes = ['borderRadius', 'BorderRadius', 'MozBorderRadius', 'WebkitBorderRadius', 'OBorderRadius', 'KhtmlBorderRadius'],
6393                     pass = false,
6394                     i;
6395                 for (i = 0; i < domPrefixes.length; i++) {
6396                     if (document.body.style[domPrefixes[i]] !== undefined) {
6397                         return true;
6398                     }
6399                 }
6400                 return pass;
6401             }
6402         },
6403         
6404         
6405         {
6406             identity: 'GeoLocation',
6407             fn: function() {
6408                 return (typeof navigator != 'undefined' && typeof navigator.geolocation != 'undefined') || (typeof google != 'undefined' && typeof google.gears != 'undefined');
6409             }
6410         },
6411         
6412         {
6413             identity: 'MouseEnterLeave',
6414             fn: function(doc, div){
6415                 return ('onmouseenter' in div && 'onmouseleave' in div);
6416             }
6417         },
6418         
6419         {
6420             identity: 'MouseWheel',
6421             fn: function(doc, div) {
6422                 return ('onmousewheel' in div);
6423             }
6424         },
6425         
6426         {
6427             identity: 'Opacity',
6428             fn: function(doc, div){
6429                 
6430                 if (Ext.isIE6 || Ext.isIE7 || Ext.isIE8) {
6431                     return false;
6432                 }
6433                 div.firstChild.style.cssText = 'opacity:0.73';
6434                 return div.firstChild.style.opacity == '0.73';
6435             }
6436         },
6437         
6438         {
6439             identity: 'Placeholder',
6440             fn: function(doc) {
6441                 return 'placeholder' in doc.createElement('input');
6442             }
6443         },
6444         
6445         
6446         {
6447             identity: 'Direct2DBug',
6448             fn: function() {
6449                 return Ext.isString(document.body.style.msTransformOrigin);
6450             }
6451         },
6452         
6453         {
6454             identity: 'BoundingClientRect',
6455             fn: function(doc, div) {
6456                 return Ext.isFunction(div.getBoundingClientRect);
6457             }
6458         },
6459         {
6460             identity: 'IncludePaddingInWidthCalculation',
6461             fn: function(doc, div){
6462                 var el = Ext.get(div.childNodes[1].firstChild);
6463                 return el.getWidth() == 210;
6464             }
6465         },
6466         {
6467             identity: 'IncludePaddingInHeightCalculation',
6468             fn: function(doc, div){
6469                 var el = Ext.get(div.childNodes[1].firstChild);
6470                 return el.getHeight() == 210;
6471             }
6472         },
6473         
6474         
6475         {
6476             identity: 'ArraySort',
6477             fn: function() {
6478                 var a = [1,2,3,4,5].sort(function(){ return 0; });
6479                 return a[0] === 1 && a[1] === 2 && a[2] === 3 && a[3] === 4 && a[4] === 5;
6480             }
6481         },
6482         
6483         {
6484             identity: 'Range',
6485             fn: function() {
6486                 return !!document.createRange;
6487             }
6488         },
6489         
6490         {
6491             identity: 'CreateContextualFragment',
6492             fn: function() {
6493                 var range = Ext.supports.Range ? document.createRange() : false;
6494                 
6495                 return range && !!range.createContextualFragment;
6496             }
6497         },
6498
6499         
6500         {
6501             identity: 'WindowOnError',
6502             fn: function () {
6503                 
6504                 return Ext.isIE || Ext.isGecko || Ext.webKitVersion >= 534.16; 
6505             }
6506         }
6507     ]
6508 };
6509
6510
6511
6512
6513
6514 Ext.ns('Ext.core');
6515 Ext.core.DomHelper = Ext.DomHelper = function(){
6516     var tempTableEl = null,
6517         emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i,
6518         tableRe = /^table|tbody|tr|td$/i,
6519         confRe = /tag|children|cn|html$/i,
6520         tableElRe = /td|tr|tbody/i,
6521         endRe = /end/i,
6522         pub,
6523         
6524         afterbegin = 'afterbegin',
6525         afterend = 'afterend',
6526         beforebegin = 'beforebegin',
6527         beforeend = 'beforeend',
6528         ts = '<table>',
6529         te = '</table>',
6530         tbs = ts+'<tbody>',
6531         tbe = '</tbody>'+te,
6532         trs = tbs + '<tr>',
6533         tre = '</tr>'+tbe;
6534
6535     
6536     function doInsert(el, o, returnElement, pos, sibling, append){
6537         el = Ext.getDom(el);
6538         var newNode;
6539         if (pub.useDom) {
6540             newNode = createDom(o, null);
6541             if (append) {
6542                 el.appendChild(newNode);
6543             } else {
6544                 (sibling == 'firstChild' ? el : el.parentNode).insertBefore(newNode, el[sibling] || el);
6545             }
6546         } else {
6547             newNode = Ext.DomHelper.insertHtml(pos, el, Ext.DomHelper.createHtml(o));
6548         }
6549         return returnElement ? Ext.get(newNode, true) : newNode;
6550     }
6551
6552     function createDom(o, parentNode){
6553         var el,
6554             doc = document,
6555             useSet,
6556             attr,
6557             val,
6558             cn;
6559
6560         if (Ext.isArray(o)) {                       
6561             el = doc.createDocumentFragment(); 
6562             for (var i = 0, l = o.length; i < l; i++) {
6563                 createDom(o[i], el);
6564             }
6565         } else if (typeof o == 'string') {         
6566             el = doc.createTextNode(o);
6567         } else {
6568             el = doc.createElement( o.tag || 'div' );
6569             useSet = !!el.setAttribute; 
6570             for (attr in o) {
6571                 if(!confRe.test(attr)){
6572                     val = o[attr];
6573                     if(attr == 'cls'){
6574                         el.className = val;
6575                     }else{
6576                         if(useSet){
6577                             el.setAttribute(attr, val);
6578                         }else{
6579                             el[attr] = val;
6580                         }
6581                     }
6582                 }
6583             }
6584             Ext.DomHelper.applyStyles(el, o.style);
6585
6586             if ((cn = o.children || o.cn)) {
6587                 createDom(cn, el);
6588             } else if (o.html) {
6589                 el.innerHTML = o.html;
6590             }
6591         }
6592         if(parentNode){
6593            parentNode.appendChild(el);
6594         }
6595         return el;
6596     }
6597
6598     
6599     function createHtml(o){
6600         var b = '',
6601             attr,
6602             val,
6603             key,
6604             cn,
6605             i;
6606
6607         if(typeof o == "string"){
6608             b = o;
6609         } else if (Ext.isArray(o)) {
6610             for (i=0; i < o.length; i++) {
6611                 if(o[i]) {
6612                     b += createHtml(o[i]);
6613                 }
6614             }
6615         } else {
6616             b += '<' + (o.tag = o.tag || 'div');
6617             for (attr in o) {
6618                 val = o[attr];
6619                 if(!confRe.test(attr)){
6620                     if (typeof val == "object") {
6621                         b += ' ' + attr + '="';
6622                         for (key in val) {
6623                             b += key + ':' + val[key] + ';';
6624                         }
6625                         b += '"';
6626                     }else{
6627                         b += ' ' + ({cls : 'class', htmlFor : 'for'}[attr] || attr) + '="' + val + '"';
6628                     }
6629                 }
6630             }
6631             
6632             if (emptyTags.test(o.tag)) {
6633                 b += '/>';
6634             } else {
6635                 b += '>';
6636                 if ((cn = o.children || o.cn)) {
6637                     b += createHtml(cn);
6638                 } else if(o.html){
6639                     b += o.html;
6640                 }
6641                 b += '</' + o.tag + '>';
6642             }
6643         }
6644         return b;
6645     }
6646
6647     function ieTable(depth, s, h, e){
6648         tempTableEl.innerHTML = [s, h, e].join('');
6649         var i = -1,
6650             el = tempTableEl,
6651             ns;
6652         while(++i < depth){
6653             el = el.firstChild;
6654         }
6655
6656         ns = el.nextSibling;
6657         if (ns){
6658             var df = document.createDocumentFragment();
6659             while(el){
6660                 ns = el.nextSibling;
6661                 df.appendChild(el);
6662                 el = ns;
6663             }
6664             el = df;
6665         }
6666         return el;
6667     }
6668
6669     
6670     function insertIntoTable(tag, where, el, html) {
6671         var node,
6672             before;
6673
6674         tempTableEl = tempTableEl || document.createElement('div');
6675
6676         if(tag == 'td' && (where == afterbegin || where == beforeend) ||
6677            !tableElRe.test(tag) && (where == beforebegin || where == afterend)) {
6678             return null;
6679         }
6680         before = where == beforebegin ? el :
6681                  where == afterend ? el.nextSibling :
6682                  where == afterbegin ? el.firstChild : null;
6683
6684         if (where == beforebegin || where == afterend) {
6685             el = el.parentNode;
6686         }
6687
6688         if (tag == 'td' || (tag == 'tr' && (where == beforeend || where == afterbegin))) {
6689             node = ieTable(4, trs, html, tre);
6690         } else if ((tag == 'tbody' && (where == beforeend || where == afterbegin)) ||
6691                    (tag == 'tr' && (where == beforebegin || where == afterend))) {
6692             node = ieTable(3, tbs, html, tbe);
6693         } else {
6694             node = ieTable(2, ts, html, te);
6695         }
6696         el.insertBefore(node, before);
6697         return node;
6698     }
6699
6700     
6701     function createContextualFragment(html){
6702         var div = document.createElement("div"),
6703             fragment = document.createDocumentFragment(),
6704             i = 0,
6705             length, childNodes;
6706
6707         div.innerHTML = html;
6708         childNodes = div.childNodes;
6709         length = childNodes.length;
6710
6711         for (; i < length; i++) {
6712             fragment.appendChild(childNodes[i].cloneNode(true));
6713         }
6714
6715         return fragment;
6716     }
6717
6718     pub = {
6719         
6720         markup : function(o){
6721             return createHtml(o);
6722         },
6723
6724         
6725         applyStyles : function(el, styles){
6726             if (styles) {
6727                 el = Ext.fly(el);
6728                 if (typeof styles == "function") {
6729                     styles = styles.call();
6730                 }
6731                 if (typeof styles == "string") {
6732                     styles = Ext.Element.parseStyles(styles);
6733                 }
6734                 if (typeof styles == "object") {
6735                     el.setStyle(styles);
6736                 }
6737             }
6738         },
6739
6740         
6741         insertHtml : function(where, el, html){
6742             var hash = {},
6743                 hashVal,
6744                 range,
6745                 rangeEl,
6746                 setStart,
6747                 frag,
6748                 rs;
6749
6750             where = where.toLowerCase();
6751             
6752             hash[beforebegin] = ['BeforeBegin', 'previousSibling'];
6753             hash[afterend] = ['AfterEnd', 'nextSibling'];
6754
6755             
6756             if (el.insertAdjacentHTML) {
6757                 if(tableRe.test(el.tagName) && (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))){
6758                     return rs;
6759                 }
6760
6761                 
6762                 hash[afterbegin] = ['AfterBegin', 'firstChild'];
6763                 hash[beforeend] = ['BeforeEnd', 'lastChild'];
6764                 if ((hashVal = hash[where])) {
6765                     el.insertAdjacentHTML(hashVal[0], html);
6766                     return el[hashVal[1]];
6767                 }
6768             
6769             } else {
6770                 
6771                 if (Ext.isTextNode(el)) {
6772                     where = where === 'afterbegin' ? 'beforebegin' : where;
6773                     where = where === 'beforeend' ? 'afterend' : where;
6774                 }
6775                 range = Ext.supports.CreateContextualFragment ? el.ownerDocument.createRange() : undefined;
6776                 setStart = 'setStart' + (endRe.test(where) ? 'After' : 'Before');
6777                 if (hash[where]) {
6778                     if (range) {
6779                         range[setStart](el);
6780                         frag = range.createContextualFragment(html);
6781                     } else {
6782                         frag = createContextualFragment(html);
6783                     }
6784                     el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);
6785                     return el[(where == beforebegin ? 'previous' : 'next') + 'Sibling'];
6786                 } else {
6787                     rangeEl = (where == afterbegin ? 'first' : 'last') + 'Child';
6788                     if (el.firstChild) {
6789                         if (range) {
6790                             range[setStart](el[rangeEl]);
6791                             frag = range.createContextualFragment(html);
6792                         } else {
6793                             frag = createContextualFragment(html);
6794                         }
6795
6796                         if(where == afterbegin){
6797                             el.insertBefore(frag, el.firstChild);
6798                         }else{
6799                             el.appendChild(frag);
6800                         }
6801                     } else {
6802                         el.innerHTML = html;
6803                     }
6804                     return el[rangeEl];
6805                 }
6806             }
6807         },
6808
6809         
6810         insertBefore : function(el, o, returnElement){
6811             return doInsert(el, o, returnElement, beforebegin);
6812         },
6813
6814         
6815         insertAfter : function(el, o, returnElement){
6816             return doInsert(el, o, returnElement, afterend, 'nextSibling');
6817         },
6818
6819         
6820         insertFirst : function(el, o, returnElement){
6821             return doInsert(el, o, returnElement, afterbegin, 'firstChild');
6822         },
6823
6824         
6825         append : function(el, o, returnElement){
6826             return doInsert(el, o, returnElement, beforeend, '', true);
6827         },
6828
6829         
6830         overwrite : function(el, o, returnElement){
6831             el = Ext.getDom(el);
6832             el.innerHTML = createHtml(o);
6833             return returnElement ? Ext.get(el.firstChild) : el.firstChild;
6834         },
6835
6836         createHtml : createHtml,
6837
6838         
6839         createDom: createDom,
6840
6841         
6842         useDom : false,
6843
6844         
6845         createTemplate : function(o){
6846             var html = Ext.DomHelper.createHtml(o);
6847             return Ext.create('Ext.Template', html);
6848         }
6849     };
6850     return pub;
6851 }();
6852
6853
6854
6855 Ext.ns('Ext.core');
6856
6857 Ext.core.DomQuery = Ext.DomQuery = function(){
6858     var cache = {},
6859         simpleCache = {},
6860         valueCache = {},
6861         nonSpace = /\S/,
6862         trimRe = /^\s+|\s+$/g,
6863         tplRe = /\{(\d+)\}/g,
6864         modeRe = /^(\s?[\/>+~]\s?|\s|$)/,
6865         tagTokenRe = /^(#)?([\w-\*]+)/,
6866         nthRe = /(\d*)n\+?(\d*)/,
6867         nthRe2 = /\D/,
6868         startIdRe = /^\s*\#/,
6869         
6870     
6871     
6872     isIE = window.ActiveXObject ? true : false,
6873     key = 30803;
6874
6875     
6876     
6877     eval("var batch = 30803;");
6878
6879     
6880     
6881     function child(parent, index){
6882         var i = 0,
6883             n = parent.firstChild;
6884         while(n){
6885             if(n.nodeType == 1){
6886                if(++i == index){
6887                    return n;
6888                }
6889             }
6890             n = n.nextSibling;
6891         }
6892         return null;
6893     }
6894
6895     
6896     function next(n){
6897         while((n = n.nextSibling) && n.nodeType != 1);
6898         return n;
6899     }
6900
6901     
6902     function prev(n){
6903         while((n = n.previousSibling) && n.nodeType != 1);
6904         return n;
6905     }
6906
6907     
6908     
6909     function children(parent){
6910         var n = parent.firstChild,
6911         nodeIndex = -1,
6912         nextNode;
6913         while(n){
6914             nextNode = n.nextSibling;
6915             
6916             if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
6917             parent.removeChild(n);
6918             }else{
6919             
6920             n.nodeIndex = ++nodeIndex;
6921             }
6922             n = nextNode;
6923         }
6924         return this;
6925     }
6926
6927
6928     
6929     
6930     function byClassName(nodeSet, cls){
6931         if(!cls){
6932             return nodeSet;
6933         }
6934         var result = [], ri = -1;
6935         for(var i = 0, ci; ci = nodeSet[i]; i++){
6936             if((' '+ci.className+' ').indexOf(cls) != -1){
6937                 result[++ri] = ci;
6938             }
6939         }
6940         return result;
6941     };
6942
6943     function attrValue(n, attr){
6944         
6945         if(!n.tagName && typeof n.length != "undefined"){
6946             n = n[0];
6947         }
6948         if(!n){
6949             return null;
6950         }
6951
6952         if(attr == "for"){
6953             return n.htmlFor;
6954         }
6955         if(attr == "class" || attr == "className"){
6956             return n.className;
6957         }
6958         return n.getAttribute(attr) || n[attr];
6959
6960     };
6961
6962
6963     
6964     
6965     
6966     function getNodes(ns, mode, tagName){
6967         var result = [], ri = -1, cs;
6968         if(!ns){
6969             return result;
6970         }
6971         tagName = tagName || "*";
6972         
6973         if(typeof ns.getElementsByTagName != "undefined"){
6974             ns = [ns];
6975         }
6976
6977         
6978         
6979         if(!mode){
6980             for(var i = 0, ni; ni = ns[i]; i++){
6981                 cs = ni.getElementsByTagName(tagName);
6982                 for(var j = 0, ci; ci = cs[j]; j++){
6983                     result[++ri] = ci;
6984                 }
6985             }
6986         
6987         
6988         } else if(mode == "/" || mode == ">"){
6989             var utag = tagName.toUpperCase();
6990             for(var i = 0, ni, cn; ni = ns[i]; i++){
6991                 cn = ni.childNodes;
6992                 for(var j = 0, cj; cj = cn[j]; j++){
6993                     if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){
6994                         result[++ri] = cj;
6995                     }
6996                 }
6997             }
6998         
6999         
7000         }else if(mode == "+"){
7001             var utag = tagName.toUpperCase();
7002             for(var i = 0, n; n = ns[i]; i++){
7003                 while((n = n.nextSibling) && n.nodeType != 1);
7004                 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
7005                     result[++ri] = n;
7006                 }
7007             }
7008         
7009         
7010         }else if(mode == "~"){
7011             var utag = tagName.toUpperCase();
7012             for(var i = 0, n; n = ns[i]; i++){
7013                 while((n = n.nextSibling)){
7014                     if (n.nodeName == utag || n.nodeName == tagName || tagName == '*'){
7015                         result[++ri] = n;
7016                     }
7017                 }
7018             }
7019         }
7020         return result;
7021     }
7022
7023     function concat(a, b){
7024         if(b.slice){
7025             return a.concat(b);
7026         }
7027         for(var i = 0, l = b.length; i < l; i++){
7028             a[a.length] = b[i];
7029         }
7030         return a;
7031     }
7032
7033     function byTag(cs, tagName){
7034         if(cs.tagName || cs == document){
7035             cs = [cs];
7036         }
7037         if(!tagName){
7038             return cs;
7039         }
7040         var result = [], ri = -1;
7041         tagName = tagName.toLowerCase();
7042         for(var i = 0, ci; ci = cs[i]; i++){
7043             if(ci.nodeType == 1 && ci.tagName.toLowerCase() == tagName){
7044                 result[++ri] = ci;
7045             }
7046         }
7047         return result;
7048     }
7049
7050     function byId(cs, id){
7051         if(cs.tagName || cs == document){
7052             cs = [cs];
7053         }
7054         if(!id){
7055             return cs;
7056         }
7057         var result = [], ri = -1;
7058         for(var i = 0, ci; ci = cs[i]; i++){
7059             if(ci && ci.id == id){
7060                 result[++ri] = ci;
7061                 return result;
7062             }
7063         }
7064         return result;
7065     }
7066
7067     
7068     
7069     function byAttribute(cs, attr, value, op, custom){
7070         var result = [],
7071             ri = -1,
7072             useGetStyle = custom == "{",
7073             fn = Ext.DomQuery.operators[op],
7074             a,
7075             xml,
7076             hasXml;
7077
7078         for(var i = 0, ci; ci = cs[i]; i++){
7079             
7080             if(ci.nodeType != 1){
7081                 continue;
7082             }
7083             
7084             if(!hasXml){
7085                 xml = Ext.DomQuery.isXml(ci);
7086                 hasXml = true;
7087             }
7088
7089             
7090             if(!xml){
7091                 if(useGetStyle){
7092                     a = Ext.DomQuery.getStyle(ci, attr);
7093                 } else if (attr == "class" || attr == "className"){
7094                     a = ci.className;
7095                 } else if (attr == "for"){
7096                     a = ci.htmlFor;
7097                 } else if (attr == "href"){
7098                     
7099                     
7100                     a = ci.getAttribute("href", 2);
7101                 } else{
7102                     a = ci.getAttribute(attr);
7103                 }
7104             }else{
7105                 a = ci.getAttribute(attr);
7106             }
7107             if((fn && fn(a, value)) || (!fn && a)){
7108                 result[++ri] = ci;
7109             }
7110         }
7111         return result;
7112     }
7113
7114     function byPseudo(cs, name, value){
7115         return Ext.DomQuery.pseudos[name](cs, value);
7116     }
7117
7118     function nodupIEXml(cs){
7119         var d = ++key,
7120             r;
7121         cs[0].setAttribute("_nodup", d);
7122         r = [cs[0]];
7123         for(var i = 1, len = cs.length; i < len; i++){
7124             var c = cs[i];
7125             if(!c.getAttribute("_nodup") != d){
7126                 c.setAttribute("_nodup", d);
7127                 r[r.length] = c;
7128             }
7129         }
7130         for(var i = 0, len = cs.length; i < len; i++){
7131             cs[i].removeAttribute("_nodup");
7132         }
7133         return r;
7134     }
7135
7136     function nodup(cs){
7137         if(!cs){
7138             return [];
7139         }
7140         var len = cs.length, c, i, r = cs, cj, ri = -1;
7141         if(!len || typeof cs.nodeType != "undefined" || len == 1){
7142             return cs;
7143         }
7144         if(isIE && typeof cs[0].selectSingleNode != "undefined"){
7145             return nodupIEXml(cs);
7146         }
7147         var d = ++key;
7148         cs[0]._nodup = d;
7149         for(i = 1; c = cs[i]; i++){
7150             if(c._nodup != d){
7151                 c._nodup = d;
7152             }else{
7153                 r = [];
7154                 for(var j = 0; j < i; j++){
7155                     r[++ri] = cs[j];
7156                 }
7157                 for(j = i+1; cj = cs[j]; j++){
7158                     if(cj._nodup != d){
7159                         cj._nodup = d;
7160                         r[++ri] = cj;
7161                     }
7162                 }
7163                 return r;
7164             }
7165         }
7166         return r;
7167     }
7168
7169     function quickDiffIEXml(c1, c2){
7170         var d = ++key,
7171             r = [];
7172         for(var i = 0, len = c1.length; i < len; i++){
7173             c1[i].setAttribute("_qdiff", d);
7174         }
7175         for(var i = 0, len = c2.length; i < len; i++){
7176             if(c2[i].getAttribute("_qdiff") != d){
7177                 r[r.length] = c2[i];
7178             }
7179         }
7180         for(var i = 0, len = c1.length; i < len; i++){
7181            c1[i].removeAttribute("_qdiff");
7182         }
7183         return r;
7184     }
7185
7186     function quickDiff(c1, c2){
7187         var len1 = c1.length,
7188             d = ++key,
7189             r = [];
7190         if(!len1){
7191             return c2;
7192         }
7193         if(isIE && typeof c1[0].selectSingleNode != "undefined"){
7194             return quickDiffIEXml(c1, c2);
7195         }
7196         for(var i = 0; i < len1; i++){
7197             c1[i]._qdiff = d;
7198         }
7199         for(var i = 0, len = c2.length; i < len; i++){
7200             if(c2[i]._qdiff != d){
7201                 r[r.length] = c2[i];
7202             }
7203         }
7204         return r;
7205     }
7206
7207     function quickId(ns, mode, root, id){
7208         if(ns == root){
7209            var d = root.ownerDocument || root;
7210            return d.getElementById(id);
7211         }
7212         ns = getNodes(ns, mode, "*");
7213         return byId(ns, id);
7214     }
7215
7216     return {
7217         getStyle : function(el, name){
7218             return Ext.fly(el).getStyle(name);
7219         },
7220         
7221         compile : function(path, type){
7222             type = type || "select";
7223
7224             
7225             var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"],
7226                 mode,
7227                 lastPath,
7228                 matchers = Ext.DomQuery.matchers,
7229                 matchersLn = matchers.length,
7230                 modeMatch,
7231                 
7232                 lmode = path.match(modeRe);
7233
7234             if(lmode && lmode[1]){
7235                 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
7236                 path = path.replace(lmode[1], "");
7237             }
7238
7239             
7240             while(path.substr(0, 1)=="/"){
7241                 path = path.substr(1);
7242             }
7243
7244             while(path && lastPath != path){
7245                 lastPath = path;
7246                 var tokenMatch = path.match(tagTokenRe);
7247                 if(type == "select"){
7248                     if(tokenMatch){
7249                         
7250                         if(tokenMatch[1] == "#"){
7251                             fn[fn.length] = 'n = quickId(n, mode, root, "'+tokenMatch[2]+'");';
7252                         }else{
7253                             fn[fn.length] = 'n = getNodes(n, mode, "'+tokenMatch[2]+'");';
7254                         }
7255                         path = path.replace(tokenMatch[0], "");
7256                     }else if(path.substr(0, 1) != '@'){
7257                         fn[fn.length] = 'n = getNodes(n, mode, "*");';
7258                     }
7259                 
7260                 }else{
7261                     if(tokenMatch){
7262                         if(tokenMatch[1] == "#"){
7263                             fn[fn.length] = 'n = byId(n, "'+tokenMatch[2]+'");';
7264                         }else{
7265                             fn[fn.length] = 'n = byTag(n, "'+tokenMatch[2]+'");';
7266                         }
7267                         path = path.replace(tokenMatch[0], "");
7268                     }
7269                 }
7270                 while(!(modeMatch = path.match(modeRe))){
7271                     var matched = false;
7272                     for(var j = 0; j < matchersLn; j++){
7273                         var t = matchers[j];
7274                         var m = path.match(t.re);
7275                         if(m){
7276                             fn[fn.length] = t.select.replace(tplRe, function(x, i){
7277                                 return m[i];
7278                             });
7279                             path = path.replace(m[0], "");
7280                             matched = true;
7281                             break;
7282                         }
7283                     }
7284                     
7285                     if(!matched){
7286                     }
7287                 }
7288                 if(modeMatch[1]){
7289                     fn[fn.length] = 'mode="'+modeMatch[1].replace(trimRe, "")+'";';
7290                     path = path.replace(modeMatch[1], "");
7291                 }
7292             }
7293             
7294             fn[fn.length] = "return nodup(n);\n}";
7295
7296             
7297             eval(fn.join(""));
7298             return f;
7299         },
7300
7301         
7302         jsSelect: function(path, root, type){
7303             
7304             root = root || document;
7305
7306             if(typeof root == "string"){
7307                 root = document.getElementById(root);
7308             }
7309             var paths = path.split(","),
7310                 results = [];
7311
7312             
7313             for(var i = 0, len = paths.length; i < len; i++){
7314                 var subPath = paths[i].replace(trimRe, "");
7315                 
7316                 if(!cache[subPath]){
7317                     cache[subPath] = Ext.DomQuery.compile(subPath);
7318                     if(!cache[subPath]){
7319                     }
7320                 }
7321                 var result = cache[subPath](root);
7322                 if(result && result != document){
7323                     results = results.concat(result);
7324                 }
7325             }
7326
7327             
7328             
7329             if(paths.length > 1){
7330                 return nodup(results);
7331             }
7332             return results;
7333         },
7334
7335         isXml: function(el) {
7336             var docEl = (el ? el.ownerDocument || el : 0).documentElement;
7337             return docEl ? docEl.nodeName !== "HTML" : false;
7338         },
7339
7340         
7341         select : document.querySelectorAll ? function(path, root, type) {
7342             root = root || document;
7343             
7344             if (!Ext.DomQuery.isXml(root) && !(Ext.isSafari3 && !Ext.isStrict)) { 
7345                 try {
7346                     
7347                     var isDocumentRoot = root.nodeType === 9,
7348                         _path = path,
7349                         _root = root;
7350
7351                     if (!isDocumentRoot && path.indexOf(',') === -1 && !startIdRe.test(path)) {
7352                         _path = '#' + Ext.id(root) + ' ' + path;
7353                         _root = root.parentNode;
7354                     }
7355                     return Ext.Array.toArray(_root.querySelectorAll(_path));
7356                 }
7357                 catch (e) {
7358                 }
7359             }
7360             return Ext.DomQuery.jsSelect.call(this, path, root, type);
7361         } : function(path, root, type) {
7362             return Ext.DomQuery.jsSelect.call(this, path, root, type);
7363         },
7364
7365         
7366         selectNode : function(path, root){
7367             return Ext.DomQuery.select(path, root)[0];
7368         },
7369
7370         
7371         selectValue : function(path, root, defaultValue){
7372             path = path.replace(trimRe, "");
7373             if(!valueCache[path]){
7374                 valueCache[path] = Ext.DomQuery.compile(path, "select");
7375             }
7376             var n = valueCache[path](root), v;
7377             n = n[0] ? n[0] : n;
7378
7379             
7380             
7381             
7382             
7383             if (typeof n.normalize == 'function') n.normalize();
7384
7385             v = (n && n.firstChild ? n.firstChild.nodeValue : null);
7386             return ((v === null||v === undefined||v==='') ? defaultValue : v);
7387         },
7388
7389         
7390         selectNumber : function(path, root, defaultValue){
7391             var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);
7392             return parseFloat(v);
7393         },
7394
7395         
7396         is : function(el, ss){
7397             if(typeof el == "string"){
7398                 el = document.getElementById(el);
7399             }
7400             var isArray = Ext.isArray(el),
7401                 result = Ext.DomQuery.filter(isArray ? el : [el], ss);
7402             return isArray ? (result.length == el.length) : (result.length > 0);
7403         },
7404
7405         
7406         filter : function(els, ss, nonMatches){
7407             ss = ss.replace(trimRe, "");
7408             if(!simpleCache[ss]){
7409                 simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");
7410             }
7411             var result = simpleCache[ss](els);
7412             return nonMatches ? quickDiff(result, els) : result;
7413         },
7414
7415         
7416         matchers : [{
7417                 re: /^\.([\w-]+)/,
7418                 select: 'n = byClassName(n, " {1} ");'
7419             }, {
7420                 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
7421                 select: 'n = byPseudo(n, "{1}", "{2}");'
7422             },{
7423                 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
7424                 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
7425             }, {
7426                 re: /^#([\w-]+)/,
7427                 select: 'n = byId(n, "{1}");'
7428             },{
7429                 re: /^@([\w-]+)/,
7430                 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
7431             }
7432         ],
7433
7434         
7435         operators : {
7436             "=" : function(a, v){
7437                 return a == v;
7438             },
7439             "!=" : function(a, v){
7440                 return a != v;
7441             },
7442             "^=" : function(a, v){
7443                 return a && a.substr(0, v.length) == v;
7444             },
7445             "$=" : function(a, v){
7446                 return a && a.substr(a.length-v.length) == v;
7447             },
7448             "*=" : function(a, v){
7449                 return a && a.indexOf(v) !== -1;
7450             },
7451             "%=" : function(a, v){
7452                 return (a % v) == 0;
7453             },
7454             "|=" : function(a, v){
7455                 return a && (a == v || a.substr(0, v.length+1) == v+'-');
7456             },
7457             "~=" : function(a, v){
7458                 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
7459             }
7460         },
7461
7462         
7463         pseudos : {
7464             "first-child" : function(c){
7465                 var r = [], ri = -1, n;
7466                 for(var i = 0, ci; ci = n = c[i]; i++){
7467                     while((n = n.previousSibling) && n.nodeType != 1);
7468                     if(!n){
7469                         r[++ri] = ci;
7470                     }
7471                 }
7472                 return r;
7473             },
7474
7475             "last-child" : function(c){
7476                 var r = [], ri = -1, n;
7477                 for(var i = 0, ci; ci = n = c[i]; i++){
7478                     while((n = n.nextSibling) && n.nodeType != 1);
7479                     if(!n){
7480                         r[++ri] = ci;
7481                     }
7482                 }
7483                 return r;
7484             },
7485
7486             "nth-child" : function(c, a) {
7487                 var r = [], ri = -1,
7488                     m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a),
7489                     f = (m[1] || 1) - 0, l = m[2] - 0;
7490                 for(var i = 0, n; n = c[i]; i++){
7491                     var pn = n.parentNode;
7492                     if (batch != pn._batch) {
7493                         var j = 0;
7494                         for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
7495                             if(cn.nodeType == 1){
7496                                cn.nodeIndex = ++j;
7497                             }
7498                         }
7499                         pn._batch = batch;
7500                     }
7501                     if (f == 1) {
7502                         if (l == 0 || n.nodeIndex == l){
7503                             r[++ri] = n;
7504                         }
7505                     } else if ((n.nodeIndex + l) % f == 0){
7506                         r[++ri] = n;
7507                     }
7508                 }
7509
7510                 return r;
7511             },
7512
7513             "only-child" : function(c){
7514                 var r = [], ri = -1;;
7515                 for(var i = 0, ci; ci = c[i]; i++){
7516                     if(!prev(ci) && !next(ci)){
7517                         r[++ri] = ci;
7518                     }
7519                 }
7520                 return r;
7521             },
7522
7523             "empty" : function(c){
7524                 var r = [], ri = -1;
7525                 for(var i = 0, ci; ci = c[i]; i++){
7526                     var cns = ci.childNodes, j = 0, cn, empty = true;
7527                     while(cn = cns[j]){
7528                         ++j;
7529                         if(cn.nodeType == 1 || cn.nodeType == 3){
7530                             empty = false;
7531                             break;
7532                         }
7533                     }
7534                     if(empty){
7535                         r[++ri] = ci;
7536                     }
7537                 }
7538                 return r;
7539             },
7540
7541             "contains" : function(c, v){
7542                 var r = [], ri = -1;
7543                 for(var i = 0, ci; ci = c[i]; i++){
7544                     if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
7545                         r[++ri] = ci;
7546                     }
7547                 }
7548                 return r;
7549             },
7550
7551             "nodeValue" : function(c, v){
7552                 var r = [], ri = -1;
7553                 for(var i = 0, ci; ci = c[i]; i++){
7554                     if(ci.firstChild && ci.firstChild.nodeValue == v){
7555                         r[++ri] = ci;
7556                     }
7557                 }
7558                 return r;
7559             },
7560
7561             "checked" : function(c){
7562                 var r = [], ri = -1;
7563                 for(var i = 0, ci; ci = c[i]; i++){
7564                     if(ci.checked == true){
7565                         r[++ri] = ci;
7566                     }
7567                 }
7568                 return r;
7569             },
7570
7571             "not" : function(c, ss){
7572                 return Ext.DomQuery.filter(c, ss, true);
7573             },
7574
7575             "any" : function(c, selectors){
7576                 var ss = selectors.split('|'),
7577                     r = [], ri = -1, s;
7578                 for(var i = 0, ci; ci = c[i]; i++){
7579                     for(var j = 0; s = ss[j]; j++){
7580                         if(Ext.DomQuery.is(ci, s)){
7581                             r[++ri] = ci;
7582                             break;
7583                         }
7584                     }
7585                 }
7586                 return r;
7587             },
7588
7589             "odd" : function(c){
7590                 return this["nth-child"](c, "odd");
7591             },
7592
7593             "even" : function(c){
7594                 return this["nth-child"](c, "even");
7595             },
7596
7597             "nth" : function(c, a){
7598                 return c[a-1] || [];
7599             },
7600
7601             "first" : function(c){
7602                 return c[0] || [];
7603             },
7604
7605             "last" : function(c){
7606                 return c[c.length-1] || [];
7607             },
7608
7609             "has" : function(c, ss){
7610                 var s = Ext.DomQuery.select,
7611                     r = [], ri = -1;
7612                 for(var i = 0, ci; ci = c[i]; i++){
7613                     if(s(ss, ci).length > 0){
7614                         r[++ri] = ci;
7615                     }
7616                 }
7617                 return r;
7618             },
7619
7620             "next" : function(c, ss){
7621                 var is = Ext.DomQuery.is,
7622                     r = [], ri = -1;
7623                 for(var i = 0, ci; ci = c[i]; i++){
7624                     var n = next(ci);
7625                     if(n && is(n, ss)){
7626                         r[++ri] = ci;
7627                     }
7628                 }
7629                 return r;
7630             },
7631
7632             "prev" : function(c, ss){
7633                 var is = Ext.DomQuery.is,
7634                     r = [], ri = -1;
7635                 for(var i = 0, ci; ci = c[i]; i++){
7636                     var n = prev(ci);
7637                     if(n && is(n, ss)){
7638                         r[++ri] = ci;
7639                     }
7640                 }
7641                 return r;
7642             }
7643         }
7644     };
7645 }();
7646
7647
7648 Ext.query = Ext.DomQuery.select;
7649
7650
7651  (function() {
7652     var DOC = document,
7653         EC = Ext.cache;
7654
7655     Ext.Element = Ext.core.Element = function(element, forceNew) {
7656         var dom = typeof element == "string" ? DOC.getElementById(element) : element,
7657         id;
7658
7659         if (!dom) {
7660             return null;
7661         }
7662
7663         id = dom.id;
7664
7665         if (!forceNew && id && EC[id]) {
7666             
7667             return EC[id].el;
7668         }
7669
7670         
7671         this.dom = dom;
7672
7673         
7674         this.id = id || Ext.id(dom);
7675     };
7676
7677     var DH = Ext.DomHelper,
7678     El = Ext.Element;
7679
7680
7681     El.prototype = {
7682         
7683         set: function(o, useSet) {
7684             var el = this.dom,
7685                 attr,
7686                 val;
7687             useSet = (useSet !== false) && !!el.setAttribute;
7688
7689             for (attr in o) {
7690                 if (o.hasOwnProperty(attr)) {
7691                     val = o[attr];
7692                     if (attr == 'style') {
7693                         DH.applyStyles(el, val);
7694                     } else if (attr == 'cls') {
7695                         el.className = val;
7696                     } else if (useSet) {
7697                         el.setAttribute(attr, val);
7698                     } else {
7699                         el[attr] = val;
7700                     }
7701                 }
7702             }
7703             return this;
7704         },
7705
7706         
7707         
7708         
7709         
7710         
7711         
7712         
7713         
7714         
7715         
7716         
7717
7718         
7719         
7720         
7721         
7722
7723
7724         
7725         
7726         
7727         
7728         
7729         
7730         
7731
7732         
7733         
7734         
7735         
7736         
7737         
7738         
7739
7740         
7741         
7742         
7743         
7744
7745         
7746         
7747         
7748         
7749         
7750         
7751         
7752         
7753
7754         
7755         defaultUnit: "px",
7756
7757         
7758         is: function(simpleSelector) {
7759             return Ext.DomQuery.is(this.dom, simpleSelector);
7760         },
7761
7762         
7763         focus: function(defer,
7764                         
7765                         dom) {
7766             var me = this;
7767             dom = dom || me.dom;
7768             try {
7769                 if (Number(defer)) {
7770                     Ext.defer(me.focus, defer, null, [null, dom]);
7771                 } else {
7772                     dom.focus();
7773                 }
7774             } catch(e) {}
7775             return me;
7776         },
7777
7778         
7779         blur: function() {
7780             try {
7781                 this.dom.blur();
7782             } catch(e) {}
7783             return this;
7784         },
7785
7786         
7787         getValue: function(asNumber) {
7788             var val = this.dom.value;
7789             return asNumber ? parseInt(val, 10) : val;
7790         },
7791
7792         
7793         addListener: function(eventName, fn, scope, options) {
7794             Ext.EventManager.on(this.dom, eventName, fn, scope || this, options);
7795             return this;
7796         },
7797
7798         
7799         removeListener: function(eventName, fn, scope) {
7800             Ext.EventManager.un(this.dom, eventName, fn, scope || this);
7801             return this;
7802         },
7803
7804         
7805         removeAllListeners: function() {
7806             Ext.EventManager.removeAll(this.dom);
7807             return this;
7808         },
7809
7810         
7811         purgeAllListeners: function() {
7812             Ext.EventManager.purgeElement(this);
7813             return this;
7814         },
7815
7816         
7817         addUnits: function(size, units) {
7818
7819             
7820             if (Ext.isNumber(size)) {
7821                 return size + (units || this.defaultUnit || 'px');
7822             }
7823
7824             
7825             if (size === "" || size == "auto" || size == null) {
7826                 return size || '';
7827             }
7828
7829             
7830             if (!unitPattern.test(size)) {
7831                 return size || '';
7832             }
7833             return size;
7834         },
7835
7836         
7837         isBorderBox: function() {
7838             return Ext.isBorderBox || noBoxAdjust[(this.dom.tagName || "").toLowerCase()];
7839         },
7840
7841         
7842         remove: function() {
7843             var me = this,
7844             dom = me.dom;
7845
7846             if (dom) {
7847                 delete me.dom;
7848                 Ext.removeNode(dom);
7849             }
7850         },
7851
7852         
7853         hover: function(overFn, outFn, scope, options) {
7854             var me = this;
7855             me.on('mouseenter', overFn, scope || me.dom, options);
7856             me.on('mouseleave', outFn, scope || me.dom, options);
7857             return me;
7858         },
7859
7860         
7861         contains: function(el) {
7862             return ! el ? false: Ext.Element.isAncestor(this.dom, el.dom ? el.dom: el);
7863         },
7864
7865         
7866         getAttributeNS: function(ns, name) {
7867             return this.getAttribute(name, ns);
7868         },
7869
7870         
7871         getAttribute: (Ext.isIE && !(Ext.isIE9 && document.documentMode === 9)) ?
7872         function(name, ns) {
7873             var d = this.dom,
7874             type;
7875             if(ns) {
7876                 type = typeof d[ns + ":" + name];
7877                 if (type != 'undefined' && type != 'unknown') {
7878                     return d[ns + ":" + name] || null;
7879                 }
7880                 return null;
7881             }
7882             if (name === "for") {
7883                 name = "htmlFor";
7884             }
7885             return d[name] || null;
7886         }: function(name, ns) {
7887             var d = this.dom;
7888             if (ns) {
7889                return d.getAttributeNS(ns, name) || d.getAttribute(ns + ":" + name);
7890             }
7891             return  d.getAttribute(name) || d[name] || null;
7892         },
7893
7894         
7895         update: function(html) {
7896             if (this.dom) {
7897                 this.dom.innerHTML = html;
7898             }
7899             return this;
7900         }
7901     };
7902
7903     var ep = El.prototype;
7904
7905     El.addMethods = function(o) {
7906         Ext.apply(ep, o);
7907     };
7908
7909     
7910     ep.on = ep.addListener;
7911
7912     
7913     ep.un = ep.removeListener;
7914
7915     
7916     ep.clearListeners = ep.removeAllListeners;
7917
7918     
7919     ep.destroy = ep.remove;
7920
7921     
7922     ep.autoBoxAdjust = true;
7923
7924     
7925     var unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
7926     docEl;
7927
7928     
7929     El.get = function(el) {
7930         var ex,
7931         elm,
7932         id;
7933         if (!el) {
7934             return null;
7935         }
7936         if (typeof el == "string") {
7937             
7938             if (! (elm = DOC.getElementById(el))) {
7939                 return null;
7940             }
7941             if (EC[el] && EC[el].el) {
7942                 ex = EC[el].el;
7943                 ex.dom = elm;
7944             } else {
7945                 ex = El.addToCache(new El(elm));
7946             }
7947             return ex;
7948         } else if (el.tagName) {
7949             
7950             if (! (id = el.id)) {
7951                 id = Ext.id(el);
7952             }
7953             if (EC[id] && EC[id].el) {
7954                 ex = EC[id].el;
7955                 ex.dom = el;
7956             } else {
7957                 ex = El.addToCache(new El(el));
7958             }
7959             return ex;
7960         } else if (el instanceof El) {
7961             if (el != docEl) {
7962                 
7963                 
7964                 
7965                 if (Ext.isIE && (el.id == undefined || el.id == '')) {
7966                     el.dom = el.dom;
7967                 } else {
7968                     el.dom = DOC.getElementById(el.id) || el.dom;
7969                 }
7970             }
7971             return el;
7972         } else if (el.isComposite) {
7973             return el;
7974         } else if (Ext.isArray(el)) {
7975             return El.select(el);
7976         } else if (el == DOC) {
7977             
7978             if (!docEl) {
7979                 var f = function() {};
7980                 f.prototype = El.prototype;
7981                 docEl = new f();
7982                 docEl.dom = DOC;
7983             }
7984             return docEl;
7985         }
7986         return null;
7987     };
7988
7989     
7990     ep.getById = (!Ext.isIE6 && !Ext.isIE7 && !Ext.isIE8) ? El.get :
7991         function (id) {
7992             var dom = this.dom,
7993                 cached, el, ret;
7994
7995             if (dom) {
7996                 el = dom.all[id];
7997                 if (el) {
7998                     
7999                     
8000                     cached = EC[id];
8001                     if (cached && cached.el) {
8002                         ret = cached.el;
8003                         ret.dom = el;
8004                     } else {
8005                         ret = El.addToCache(new El(el));
8006                     }
8007                     return ret;
8008                 }
8009             }
8010
8011             return El.get(id);
8012         };
8013
8014     El.addToCache = function(el, id) {
8015         if (el) {
8016             id = id || el.id;
8017             EC[id] = {
8018                 el: el,
8019                 data: {},
8020                 events: {}
8021             };
8022         }
8023         return el;
8024     };
8025
8026     
8027     El.data = function(el, key, value) {
8028         el = El.get(el);
8029         if (!el) {
8030             return null;
8031         }
8032         var c = EC[el.id].data;
8033         if (arguments.length == 2) {
8034             return c[key];
8035         } else {
8036             return (c[key] = value);
8037         }
8038     };
8039
8040     
8041     
8042     
8043     function garbageCollect() {
8044         if (!Ext.enableGarbageCollector) {
8045             clearInterval(El.collectorThreadId);
8046         } else {
8047             var eid,
8048             el,
8049             d,
8050             o;
8051
8052             for (eid in EC) {
8053                 if (!EC.hasOwnProperty(eid)) {
8054                     continue;
8055                 }
8056                 o = EC[eid];
8057                 if (o.skipGarbageCollection) {
8058                     continue;
8059                 }
8060                 el = o.el;
8061                 d = el.dom;
8062                 
8063                 
8064                 
8065                 
8066                 
8067                 
8068                 
8069                 
8070                 
8071                 
8072                 
8073                 
8074                 
8075                 
8076                 
8077                 
8078                 
8079                 if (!d || !d.parentNode || (!d.offsetParent && !DOC.getElementById(eid))) {
8080                     if (d && Ext.enableListenerCollection) {
8081                         Ext.EventManager.removeAll(d);
8082                     }
8083                     delete EC[eid];
8084                 }
8085             }
8086             
8087             if (Ext.isIE) {
8088                 var t = {};
8089                 for (eid in EC) {
8090                     if (!EC.hasOwnProperty(eid)) {
8091                         continue;
8092                     }
8093                     t[eid] = EC[eid];
8094                 }
8095                 EC = Ext.cache = t;
8096             }
8097         }
8098     }
8099     El.collectorThreadId = setInterval(garbageCollect, 30000);
8100
8101     var flyFn = function() {};
8102     flyFn.prototype = El.prototype;
8103
8104     
8105     El.Flyweight = function(dom) {
8106         this.dom = dom;
8107     };
8108
8109     El.Flyweight.prototype = new flyFn();
8110     El.Flyweight.prototype.isFlyweight = true;
8111     El._flyweights = {};
8112
8113     
8114     El.fly = function(el, named) {
8115         var ret = null;
8116         named = named || '_global';
8117         el = Ext.getDom(el);
8118         if (el) {
8119             (El._flyweights[named] = El._flyweights[named] || new El.Flyweight()).dom = el;
8120             ret = El._flyweights[named];
8121         }
8122         return ret;
8123     };
8124
8125     
8126     Ext.get = El.get;
8127
8128     
8129     Ext.fly = El.fly;
8130
8131     
8132     var noBoxAdjust = Ext.isStrict ? {
8133         select: 1
8134     }: {
8135         input: 1,
8136         select: 1,
8137         textarea: 1
8138     };
8139     if (Ext.isIE || Ext.isGecko) {
8140         noBoxAdjust['button'] = 1;
8141     }
8142 })();
8143
8144
8145 Ext.Element.addMethods({
8146     
8147     findParent : function(simpleSelector, maxDepth, returnEl) {
8148         var p = this.dom,
8149             b = document.body,
8150             depth = 0,
8151             stopEl;
8152
8153         maxDepth = maxDepth || 50;
8154         if (isNaN(maxDepth)) {
8155             stopEl = Ext.getDom(maxDepth);
8156             maxDepth = Number.MAX_VALUE;
8157         }
8158         while (p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl) {
8159             if (Ext.DomQuery.is(p, simpleSelector)) {
8160                 return returnEl ? Ext.get(p) : p;
8161             }
8162             depth++;
8163             p = p.parentNode;
8164         }
8165         return null;
8166     },
8167
8168     
8169     findParentNode : function(simpleSelector, maxDepth, returnEl) {
8170         var p = Ext.fly(this.dom.parentNode, '_internal');
8171         return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
8172     },
8173
8174     
8175     up : function(simpleSelector, maxDepth) {
8176         return this.findParentNode(simpleSelector, maxDepth, true);
8177     },
8178
8179     
8180     select : function(selector) {
8181         return Ext.Element.select(selector, false,  this.dom);
8182     },
8183
8184     
8185     query : function(selector) {
8186         return Ext.DomQuery.select(selector, this.dom);
8187     },
8188
8189     
8190     down : function(selector, returnDom) {
8191         var n = Ext.DomQuery.selectNode(selector, this.dom);
8192         return returnDom ? n : Ext.get(n);
8193     },
8194
8195     
8196     child : function(selector, returnDom) {
8197         var node,
8198             me = this,
8199             id;
8200         id = Ext.get(me).id;
8201         
8202         id = id.replace(/[\.:]/g, "\\$0");
8203         node = Ext.DomQuery.selectNode('#' + id + " > " + selector, me.dom);
8204         return returnDom ? node : Ext.get(node);
8205     },
8206
8207      
8208     parent : function(selector, returnDom) {
8209         return this.matchNode('parentNode', 'parentNode', selector, returnDom);
8210     },
8211
8212      
8213     next : function(selector, returnDom) {
8214         return this.matchNode('nextSibling', 'nextSibling', selector, returnDom);
8215     },
8216
8217     
8218     prev : function(selector, returnDom) {
8219         return this.matchNode('previousSibling', 'previousSibling', selector, returnDom);
8220     },
8221
8222
8223     
8224     first : function(selector, returnDom) {
8225         return this.matchNode('nextSibling', 'firstChild', selector, returnDom);
8226     },
8227
8228     
8229     last : function(selector, returnDom) {
8230         return this.matchNode('previousSibling', 'lastChild', selector, returnDom);
8231     },
8232
8233     matchNode : function(dir, start, selector, returnDom) {
8234         if (!this.dom) {
8235             return null;
8236         }
8237
8238         var n = this.dom[start];
8239         while (n) {
8240             if (n.nodeType == 1 && (!selector || Ext.DomQuery.is(n, selector))) {
8241                 return !returnDom ? Ext.get(n) : n;
8242             }
8243             n = n[dir];
8244         }
8245         return null;
8246     }
8247 });
8248
8249
8250 Ext.Element.addMethods({
8251     
8252     appendChild : function(el) {
8253         return Ext.get(el).appendTo(this);
8254     },
8255
8256     
8257     appendTo : function(el) {
8258         Ext.getDom(el).appendChild(this.dom);
8259         return this;
8260     },
8261
8262     
8263     insertBefore : function(el) {
8264         el = Ext.getDom(el);
8265         el.parentNode.insertBefore(this.dom, el);
8266         return this;
8267     },
8268
8269     
8270     insertAfter : function(el) {
8271         el = Ext.getDom(el);
8272         el.parentNode.insertBefore(this.dom, el.nextSibling);
8273         return this;
8274     },
8275
8276     
8277     insertFirst : function(el, returnDom) {
8278         el = el || {};
8279         if (el.nodeType || el.dom || typeof el == 'string') { 
8280             el = Ext.getDom(el);
8281             this.dom.insertBefore(el, this.dom.firstChild);
8282             return !returnDom ? Ext.get(el) : el;
8283         }
8284         else { 
8285             return this.createChild(el, this.dom.firstChild, returnDom);
8286         }
8287     },
8288
8289     
8290     insertSibling: function(el, where, returnDom){
8291         var me = this, rt,
8292         isAfter = (where || 'before').toLowerCase() == 'after',
8293         insertEl;
8294
8295         if(Ext.isArray(el)){
8296             insertEl = me;
8297             Ext.each(el, function(e) {
8298                 rt = Ext.fly(insertEl, '_internal').insertSibling(e, where, returnDom);
8299                 if(isAfter){
8300                     insertEl = rt;
8301                 }
8302             });
8303             return rt;
8304         }
8305
8306         el = el || {};
8307
8308         if(el.nodeType || el.dom){
8309             rt = me.dom.parentNode.insertBefore(Ext.getDom(el), isAfter ? me.dom.nextSibling : me.dom);
8310             if (!returnDom) {
8311                 rt = Ext.get(rt);
8312             }
8313         }else{
8314             if (isAfter && !me.dom.nextSibling) {
8315                 rt = Ext.DomHelper.append(me.dom.parentNode, el, !returnDom);
8316             } else {
8317                 rt = Ext.DomHelper[isAfter ? 'insertAfter' : 'insertBefore'](me.dom, el, !returnDom);
8318             }
8319         }
8320         return rt;
8321     },
8322
8323     
8324     replace : function(el) {
8325         el = Ext.get(el);
8326         this.insertBefore(el);
8327         el.remove();
8328         return this;
8329     },
8330     
8331     
8332     replaceWith: function(el){
8333         var me = this;
8334             
8335         if(el.nodeType || el.dom || typeof el == 'string'){
8336             el = Ext.get(el);
8337             me.dom.parentNode.insertBefore(el, me.dom);
8338         }else{
8339             el = Ext.DomHelper.insertBefore(me.dom, el);
8340         }
8341         
8342         delete Ext.cache[me.id];
8343         Ext.removeNode(me.dom);      
8344         me.id = Ext.id(me.dom = el);
8345         Ext.Element.addToCache(me.isFlyweight ? new Ext.Element(me.dom) : me);     
8346         return me;
8347     },
8348     
8349     
8350     createChild : function(config, insertBefore, returnDom) {
8351         config = config || {tag:'div'};
8352         if (insertBefore) {
8353             return Ext.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
8354         }
8355         else {
8356             return Ext.DomHelper[!this.dom.firstChild ? 'insertFirst' : 'append'](this.dom, config,  returnDom !== true);
8357         }
8358     },
8359
8360     
8361     wrap : function(config, returnDom) {
8362         var newEl = Ext.DomHelper.insertBefore(this.dom, config || {tag: "div"}, !returnDom),
8363             d = newEl.dom || newEl;
8364
8365         d.appendChild(this.dom);
8366         return newEl;
8367     },
8368
8369     
8370     insertHtml : function(where, html, returnEl) {
8371         var el = Ext.DomHelper.insertHtml(where, this.dom, html);
8372         return returnEl ? Ext.get(el) : el;
8373     }
8374 });
8375
8376
8377 (function(){
8378     
8379     var ELEMENT = Ext.Element,
8380         supports = Ext.supports,
8381         view = document.defaultView,
8382         opacityRe = /alpha\(opacity=(.*)\)/i,
8383         trimRe = /^\s+|\s+$/g,
8384         spacesRe = /\s+/,
8385         wordsRe = /\w/g,
8386         adjustDirect2DTableRe = /table-row|table-.*-group/,
8387         INTERNAL = '_internal',
8388         PADDING = 'padding',
8389         MARGIN = 'margin',
8390         BORDER = 'border',
8391         LEFT = '-left',
8392         RIGHT = '-right',
8393         TOP = '-top',
8394         BOTTOM = '-bottom',
8395         WIDTH = '-width',
8396         MATH = Math,
8397         HIDDEN = 'hidden',
8398         ISCLIPPED = 'isClipped',
8399         OVERFLOW = 'overflow',
8400         OVERFLOWX = 'overflow-x',
8401         OVERFLOWY = 'overflow-y',
8402         ORIGINALCLIP = 'originalClip',
8403         
8404         borders = {l: BORDER + LEFT + WIDTH, r: BORDER + RIGHT + WIDTH, t: BORDER + TOP + WIDTH, b: BORDER + BOTTOM + WIDTH},
8405         paddings = {l: PADDING + LEFT, r: PADDING + RIGHT, t: PADDING + TOP, b: PADDING + BOTTOM},
8406         margins = {l: MARGIN + LEFT, r: MARGIN + RIGHT, t: MARGIN + TOP, b: MARGIN + BOTTOM},
8407         data = ELEMENT.data;
8408
8409     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>';
8410
8411     
8412     
8413     ELEMENT.inheritedProps = {
8414         fontSize: 1,
8415         fontStyle: 1,
8416         opacity: 1
8417     };
8418
8419     Ext.override(ELEMENT, {
8420
8421         
8422         
8423         adjustWidth : function(width) {
8424             var me = this,
8425                 isNum = (typeof width == 'number');
8426
8427             if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
8428                width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
8429             }
8430             return (isNum && width < 0) ? 0 : width;
8431         },
8432
8433         
8434         adjustHeight : function(height) {
8435             var me = this,
8436                 isNum = (typeof height == "number");
8437
8438             if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
8439                height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
8440             }
8441             return (isNum && height < 0) ? 0 : height;
8442         },
8443
8444
8445         
8446         addCls : function(className){
8447             var me = this,
8448                 cls = [],
8449                 space = ((me.dom.className.replace(trimRe, '') == '') ? "" : " "),
8450                 i, len, v;
8451             if (className === undefined) {
8452                 return me;
8453             }
8454             
8455             if (Object.prototype.toString.call(className) !== '[object Array]') {
8456                 if (typeof className === 'string') {
8457                     className = className.replace(trimRe, '').split(spacesRe);
8458                     if (className.length === 1) {
8459                         className = className[0];
8460                         if (!me.hasCls(className)) {
8461                             me.dom.className += space + className;
8462                         }
8463                     } else {
8464                         this.addCls(className);
8465                     }
8466                 }
8467             } else {
8468                 for (i = 0, len = className.length; i < len; i++) {
8469                     v = className[i];
8470                     if (typeof v == 'string' && (' ' + me.dom.className + ' ').indexOf(' ' + v + ' ') == -1) {
8471                         cls.push(v);
8472                     }
8473                 }
8474                 if (cls.length) {
8475                     me.dom.className += space + cls.join(" ");
8476                 }
8477             }
8478             return me;
8479         },
8480
8481         
8482         removeCls : function(className){
8483             var me = this,
8484                 i, idx, len, cls, elClasses;
8485             if (className === undefined) {
8486                 return me;
8487             }
8488             if (Object.prototype.toString.call(className) !== '[object Array]') {
8489                 className = className.replace(trimRe, '').split(spacesRe);
8490             }
8491             if (me.dom && me.dom.className) {
8492                 elClasses = me.dom.className.replace(trimRe, '').split(spacesRe);
8493                 for (i = 0, len = className.length; i < len; i++) {
8494                     cls = className[i];
8495                     if (typeof cls == 'string') {
8496                         cls = cls.replace(trimRe, '');
8497                         idx = Ext.Array.indexOf(elClasses, cls);
8498                         if (idx != -1) {
8499                             Ext.Array.erase(elClasses, idx, 1);
8500                         }
8501                     }
8502                 }
8503                 me.dom.className = elClasses.join(" ");
8504             }
8505             return me;
8506         },
8507
8508         
8509         radioCls : function(className){
8510             var cn = this.dom.parentNode.childNodes,
8511                 v, i, len;
8512             className = Ext.isArray(className) ? className : [className];
8513             for (i = 0, len = cn.length; i < len; i++) {
8514                 v = cn[i];
8515                 if (v && v.nodeType == 1) {
8516                     Ext.fly(v, '_internal').removeCls(className);
8517                 }
8518             }
8519             return this.addCls(className);
8520         },
8521
8522         
8523         toggleCls : Ext.supports.ClassList ?
8524             function(className) {
8525                 this.dom.classList.toggle(Ext.String.trim(className));
8526                 return this;
8527             } :
8528             function(className) {
8529                 return this.hasCls(className) ? this.removeCls(className) : this.addCls(className);
8530             },
8531
8532         
8533         hasCls : Ext.supports.ClassList ?
8534             function(className) {
8535                 if (!className) {
8536                     return false;
8537                 }
8538                 className = className.split(spacesRe);
8539                 var ln = className.length,
8540                     i = 0;
8541                 for (; i < ln; i++) {
8542                     if (className[i] && this.dom.classList.contains(className[i])) {
8543                         return true;
8544                     }
8545                 }
8546                 return false;
8547             } :
8548             function(className){
8549                 return className && (' ' + this.dom.className + ' ').indexOf(' ' + className + ' ') != -1;
8550             },
8551
8552         
8553         replaceCls : function(oldClassName, newClassName){
8554             return this.removeCls(oldClassName).addCls(newClassName);
8555         },
8556
8557         isStyle : function(style, val) {
8558             return this.getStyle(style) == val;
8559         },
8560
8561         
8562         getStyle : function() {
8563             return view && view.getComputedStyle ?
8564                 function(prop){
8565                     var el = this.dom,
8566                         v, cs, out, display, cleaner;
8567
8568                     if(el == document){
8569                         return null;
8570                     }
8571                     prop = ELEMENT.normalize(prop);
8572                     out = (v = el.style[prop]) ? v :
8573                            (cs = view.getComputedStyle(el, "")) ? cs[prop] : null;
8574
8575                     
8576                     
8577                     if(prop == 'marginRight' && out != '0px' && !supports.RightMargin){
8578                         cleaner = ELEMENT.getRightMarginFixCleaner(el);
8579                         display = this.getStyle('display');
8580                         el.style.display = 'inline-block';
8581                         out = view.getComputedStyle(el, '').marginRight;
8582                         el.style.display = display;
8583                         cleaner();
8584                     }
8585
8586                     if(prop == 'backgroundColor' && out == 'rgba(0, 0, 0, 0)' && !supports.TransparentColor){
8587                         out = 'transparent';
8588                     }
8589                     return out;
8590                 } :
8591                 function (prop) {
8592                     var el = this.dom,
8593                         m, cs;
8594
8595                     if (el == document) {
8596                         return null;
8597                     }
8598                     prop = ELEMENT.normalize(prop);
8599
8600                     do {
8601                         if (prop == 'opacity') {
8602                             if (el.style.filter.match) {
8603                                 m = el.style.filter.match(opacityRe);
8604                                 if(m){
8605                                     var fv = parseFloat(m[1]);
8606                                     if(!isNaN(fv)){
8607                                         return fv ? fv / 100 : 0;
8608                                     }
8609                                 }
8610                             }
8611                             return 1;
8612                         }
8613
8614                         
8615                         
8616                         if (!Ext.isIE6) {
8617                             return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
8618                         }
8619
8620                         try {
8621                             return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
8622                         } catch (e) {
8623                             
8624                             
8625                         }
8626
8627                         if (!ELEMENT.inheritedProps[prop]) {
8628                             break;
8629                         }
8630
8631                         el = el.parentNode;
8632                         
8633                         
8634                         
8635                     } while (el);
8636
8637                     return null;
8638                 }
8639         }(),
8640
8641         
8642         getColor : function(attr, defaultValue, prefix){
8643             var v = this.getStyle(attr),
8644                 color = prefix || prefix === '' ? prefix : '#',
8645                 h;
8646
8647             if(!v || (/transparent|inherit/.test(v))) {
8648                 return defaultValue;
8649             }
8650             if(/^r/.test(v)){
8651                 Ext.each(v.slice(4, v.length -1).split(','), function(s){
8652                     h = parseInt(s, 10);
8653                     color += (h < 16 ? '0' : '') + h.toString(16);
8654                 });
8655             }else{
8656                 v = v.replace('#', '');
8657                 color += v.length == 3 ? v.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : v;
8658             }
8659             return(color.length > 5 ? color.toLowerCase() : defaultValue);
8660         },
8661
8662         
8663         setStyle : function(prop, value){
8664             var me = this,
8665                 tmp, style;
8666
8667             if (!me.dom) {
8668                 return me;
8669             }
8670             if (typeof prop === 'string') {
8671                 tmp = {};
8672                 tmp[prop] = value;
8673                 prop = tmp;
8674             }
8675             for (style in prop) {
8676                 if (prop.hasOwnProperty(style)) {
8677                     value = Ext.value(prop[style], '');
8678                     if (style == 'opacity') {
8679                         me.setOpacity(value);
8680                     }
8681                     else {
8682                         me.dom.style[ELEMENT.normalize(style)] = value;
8683                     }
8684                 }
8685             }
8686             return me;
8687         },
8688
8689         
8690         setOpacity: function(opacity, animate) {
8691             var me = this,
8692                 dom = me.dom,
8693                 val,
8694                 style;
8695
8696             if (!me.dom) {
8697                 return me;
8698             }
8699
8700             style = me.dom.style;
8701
8702             if (!animate || !me.anim) {
8703                 if (!Ext.supports.Opacity) {
8704                     opacity = opacity < 1 ? 'alpha(opacity=' + opacity * 100 + ')': '';
8705                     val = style.filter.replace(opacityRe, '').replace(trimRe, '');
8706
8707                     style.zoom = 1;
8708                     style.filter = val + (val.length > 0 ? ' ': '') + opacity;
8709                 }
8710                 else {
8711                     style.opacity = opacity;
8712                 }
8713             }
8714             else {
8715                 if (!Ext.isObject(animate)) {
8716                     animate = {
8717                         duration: 350,
8718                         easing: 'ease-in'
8719                     };
8720                 }
8721                 me.animate(Ext.applyIf({
8722                     to: {
8723                         opacity: opacity
8724                     }
8725                 },
8726                 animate));
8727             }
8728             return me;
8729         },
8730
8731
8732         
8733         clearOpacity : function(){
8734             var style = this.dom.style;
8735             if(!Ext.supports.Opacity){
8736                 if(!Ext.isEmpty(style.filter)){
8737                     style.filter = style.filter.replace(opacityRe, '').replace(trimRe, '');
8738                 }
8739             }else{
8740                 style.opacity = style['-moz-opacity'] = style['-khtml-opacity'] = '';
8741             }
8742             return this;
8743         },
8744
8745         
8746         adjustDirect2DDimension: function(dimension) {
8747             var me = this,
8748                 dom = me.dom,
8749                 display = me.getStyle('display'),
8750                 inlineDisplay = dom.style['display'],
8751                 inlinePosition = dom.style['position'],
8752                 originIndex = dimension === 'width' ? 0 : 1,
8753                 floating;
8754
8755             if (display === 'inline') {
8756                 dom.style['display'] = 'inline-block';
8757             }
8758
8759             dom.style['position'] = display.match(adjustDirect2DTableRe) ? 'absolute' : 'static';
8760
8761             
8762             
8763             floating = (parseFloat(me.getStyle(dimension)) || parseFloat(dom.currentStyle.msTransformOrigin.split(' ')[originIndex]) * 2) % 1;
8764
8765             dom.style['position'] = inlinePosition;
8766
8767             if (display === 'inline') {
8768                 dom.style['display'] = inlineDisplay;
8769             }
8770
8771             return floating;
8772         },
8773
8774         
8775         getHeight: function(contentHeight, preciseHeight) {
8776             var me = this,
8777                 dom = me.dom,
8778                 hidden = Ext.isIE && me.isStyle('display', 'none'),
8779                 height, overflow, style, floating;
8780
8781             
8782             
8783             if (Ext.isIEQuirks) {
8784                 style = dom.style;
8785                 overflow = style.overflow;
8786                 me.setStyle({ overflow: 'hidden'});
8787             }
8788
8789             height = dom.offsetHeight;
8790
8791             height = MATH.max(height, hidden ? 0 : dom.clientHeight) || 0;
8792
8793             
8794             if (!hidden && Ext.supports.Direct2DBug) {
8795                 floating = me.adjustDirect2DDimension('height');
8796                 if (preciseHeight) {
8797                     height += floating;
8798                 }
8799                 else if (floating > 0 && floating < 0.5) {
8800                     height++;
8801                 }
8802             }
8803
8804             if (contentHeight) {
8805                 height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
8806             }
8807
8808             if (Ext.isIEQuirks) {
8809                 me.setStyle({ overflow: overflow});
8810             }
8811
8812             if (height < 0) {
8813                 height = 0;
8814             }
8815             return height;
8816         },
8817
8818         
8819         getWidth: function(contentWidth, preciseWidth) {
8820             var me = this,
8821                 dom = me.dom,
8822                 hidden = Ext.isIE && me.isStyle('display', 'none'),
8823                 rect, width, overflow, style, floating, parentPosition;
8824
8825             
8826             
8827             if (Ext.isIEQuirks) {
8828                 style = dom.style;
8829                 overflow = style.overflow;
8830                 me.setStyle({overflow: 'hidden'});
8831             }
8832
8833             
8834             if (Ext.isOpera10_5) {
8835                 if (dom.parentNode.currentStyle.position === 'relative') {
8836                     parentPosition = dom.parentNode.style.position;
8837                     dom.parentNode.style.position = 'static';
8838                     width = dom.offsetWidth;
8839                     dom.parentNode.style.position = parentPosition;
8840                 }
8841                 width = Math.max(width || 0, dom.offsetWidth);
8842
8843             
8844             
8845             
8846             
8847             
8848             } else if (Ext.supports.BoundingClientRect) {
8849                 rect = dom.getBoundingClientRect();
8850                 width = rect.right - rect.left;
8851                 width = preciseWidth ? width : Math.ceil(width);
8852             } else {
8853                 width = dom.offsetWidth;
8854             }
8855
8856             width = MATH.max(width, hidden ? 0 : dom.clientWidth) || 0;
8857
8858             
8859             if (!hidden && Ext.supports.Direct2DBug) {
8860                 floating = me.adjustDirect2DDimension('width');
8861                 if (preciseWidth) {
8862                     width += floating;
8863                 }
8864                 else if (floating > 0 && floating < 0.5) {
8865                     width++;
8866                 }
8867             }
8868
8869             if (contentWidth) {
8870                 width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
8871             }
8872
8873             if (Ext.isIEQuirks) {
8874                 me.setStyle({ overflow: overflow});
8875             }
8876
8877             if (width < 0) {
8878                 width = 0;
8879             }
8880             return width;
8881         },
8882
8883         
8884         setWidth : function(width, animate){
8885             var me = this;
8886             width = me.adjustWidth(width);
8887             if (!animate || !me.anim) {
8888                 me.dom.style.width = me.addUnits(width);
8889             }
8890             else {
8891                 if (!Ext.isObject(animate)) {
8892                     animate = {};
8893                 }
8894                 me.animate(Ext.applyIf({
8895                     to: {
8896                         width: width
8897                     }
8898                 }, animate));
8899             }
8900             return me;
8901         },
8902
8903         
8904          setHeight : function(height, animate){
8905             var me = this;
8906             height = me.adjustHeight(height);
8907             if (!animate || !me.anim) {
8908                 me.dom.style.height = me.addUnits(height);
8909             }
8910             else {
8911                 if (!Ext.isObject(animate)) {
8912                     animate = {};
8913                 }
8914                 me.animate(Ext.applyIf({
8915                     to: {
8916                         height: height
8917                     }
8918                 }, animate));
8919             }
8920             return me;
8921         },
8922
8923         
8924         getBorderWidth : function(side){
8925             return this.addStyles(side, borders);
8926         },
8927
8928         
8929         getPadding : function(side){
8930             return this.addStyles(side, paddings);
8931         },
8932
8933         
8934         clip : function(){
8935             var me = this,
8936                 dom = me.dom;
8937
8938             if(!data(dom, ISCLIPPED)){
8939                 data(dom, ISCLIPPED, true);
8940                 data(dom, ORIGINALCLIP, {
8941                     o: me.getStyle(OVERFLOW),
8942                     x: me.getStyle(OVERFLOWX),
8943                     y: me.getStyle(OVERFLOWY)
8944                 });
8945                 me.setStyle(OVERFLOW, HIDDEN);
8946                 me.setStyle(OVERFLOWX, HIDDEN);
8947                 me.setStyle(OVERFLOWY, HIDDEN);
8948             }
8949             return me;
8950         },
8951
8952         
8953         unclip : function(){
8954             var me = this,
8955                 dom = me.dom,
8956                 clip;
8957
8958             if(data(dom, ISCLIPPED)){
8959                 data(dom, ISCLIPPED, false);
8960                 clip = data(dom, ORIGINALCLIP);
8961                 if(clip.o){
8962                     me.setStyle(OVERFLOW, clip.o);
8963                 }
8964                 if(clip.x){
8965                     me.setStyle(OVERFLOWX, clip.x);
8966                 }
8967                 if(clip.y){
8968                     me.setStyle(OVERFLOWY, clip.y);
8969                 }
8970             }
8971             return me;
8972         },
8973
8974         
8975         addStyles : function(sides, styles){
8976             var totalSize = 0,
8977                 sidesArr = sides.match(wordsRe),
8978                 i = 0,
8979                 len = sidesArr.length,
8980                 side, size;
8981             for (; i < len; i++) {
8982                 side = sidesArr[i];
8983                 size = side && parseInt(this.getStyle(styles[side]), 10);
8984                 if (size) {
8985                     totalSize += MATH.abs(size);
8986                 }
8987             }
8988             return totalSize;
8989         },
8990
8991         margins : margins,
8992
8993         
8994         applyStyles : function(style){
8995             Ext.DomHelper.applyStyles(this.dom, style);
8996             return this;
8997         },
8998
8999         
9000         getStyles : function(){
9001             var styles = {},
9002                 len = arguments.length,
9003                 i = 0, style;
9004
9005             for(; i < len; ++i) {
9006                 style = arguments[i];
9007                 styles[style] = this.getStyle(style);
9008             }
9009             return styles;
9010         },
9011
9012        
9013         boxWrap : function(cls){
9014             cls = cls || Ext.baseCSSPrefix + 'box';
9015             var el = Ext.get(this.insertHtml("beforeBegin", "<div class='" + cls + "'>" + Ext.String.format(ELEMENT.boxMarkup, cls) + "</div>"));
9016             Ext.DomQuery.selectNode('.' + cls + '-mc', el.dom).appendChild(this.dom);
9017             return el;
9018         },
9019
9020         
9021         setSize : function(width, height, animate){
9022             var me = this;
9023             if (Ext.isObject(width)) { 
9024                 animate = height;
9025                 height = width.height;
9026                 width = width.width;
9027             }
9028             width = me.adjustWidth(width);
9029             height = me.adjustHeight(height);
9030             if(!animate || !me.anim){
9031                 
9032                 
9033                 if (!Ext.isIEQuirks && (Ext.isIE6 || Ext.isIE7)) {
9034                     me.dom.offsetTop;
9035                 }
9036                 me.dom.style.width = me.addUnits(width);
9037                 me.dom.style.height = me.addUnits(height);
9038             }
9039             else {
9040                 if (animate === true) {
9041                     animate = {};
9042                 }
9043                 me.animate(Ext.applyIf({
9044                     to: {
9045                         width: width,
9046                         height: height
9047                     }
9048                 }, animate));
9049             }
9050             return me;
9051         },
9052
9053         
9054         getComputedHeight : function(){
9055             var me = this,
9056                 h = Math.max(me.dom.offsetHeight, me.dom.clientHeight);
9057             if(!h){
9058                 h = parseFloat(me.getStyle('height')) || 0;
9059                 if(!me.isBorderBox()){
9060                     h += me.getFrameWidth('tb');
9061                 }
9062             }
9063             return h;
9064         },
9065
9066         
9067         getComputedWidth : function(){
9068             var me = this,
9069                 w = Math.max(me.dom.offsetWidth, me.dom.clientWidth);
9070
9071             if(!w){
9072                 w = parseFloat(me.getStyle('width')) || 0;
9073                 if(!me.isBorderBox()){
9074                     w += me.getFrameWidth('lr');
9075                 }
9076             }
9077             return w;
9078         },
9079
9080         
9081         getFrameWidth : function(sides, onlyContentBox){
9082             return onlyContentBox && this.isBorderBox() ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
9083         },
9084
9085         
9086         addClsOnOver : function(className){
9087             var dom = this.dom;
9088             this.hover(
9089                 function(){
9090                     Ext.fly(dom, INTERNAL).addCls(className);
9091                 },
9092                 function(){
9093                     Ext.fly(dom, INTERNAL).removeCls(className);
9094                 }
9095             );
9096             return this;
9097         },
9098
9099         
9100         addClsOnFocus : function(className){
9101             var me = this,
9102                 dom = me.dom;
9103             me.on("focus", function(){
9104                 Ext.fly(dom, INTERNAL).addCls(className);
9105             });
9106             me.on("blur", function(){
9107                 Ext.fly(dom, INTERNAL).removeCls(className);
9108             });
9109             return me;
9110         },
9111
9112         
9113         addClsOnClick : function(className){
9114             var dom = this.dom;
9115             this.on("mousedown", function(){
9116                 Ext.fly(dom, INTERNAL).addCls(className);
9117                 var d = Ext.getDoc(),
9118                     fn = function(){
9119                         Ext.fly(dom, INTERNAL).removeCls(className);
9120                         d.removeListener("mouseup", fn);
9121                     };
9122                 d.on("mouseup", fn);
9123             });
9124             return this;
9125         },
9126
9127         
9128
9129         getViewSize : function(){
9130             var me = this,
9131                 dom = me.dom,
9132                 isDoc = (dom == Ext.getDoc().dom || dom == Ext.getBody().dom),
9133                 style, overflow, ret;
9134
9135             
9136             if (isDoc) {
9137                 ret = {
9138                     width : ELEMENT.getViewWidth(),
9139                     height : ELEMENT.getViewHeight()
9140                 };
9141
9142             
9143             }
9144             else {
9145                 
9146                 
9147                 if (Ext.isIE6 || Ext.isIEQuirks) {
9148                     style = dom.style;
9149                     overflow = style.overflow;
9150                     me.setStyle({ overflow: 'hidden'});
9151                 }
9152                 ret = {
9153                     width : dom.clientWidth,
9154                     height : dom.clientHeight
9155                 };
9156                 if (Ext.isIE6 || Ext.isIEQuirks) {
9157                     me.setStyle({ overflow: overflow });
9158                 }
9159             }
9160             return ret;
9161         },
9162
9163         
9164
9165         getStyleSize : function(){
9166             var me = this,
9167                 doc = document,
9168                 d = this.dom,
9169                 isDoc = (d == doc || d == doc.body),
9170                 s = d.style,
9171                 w, h;
9172
9173             
9174             if (isDoc) {
9175                 return {
9176                     width : ELEMENT.getViewWidth(),
9177                     height : ELEMENT.getViewHeight()
9178                 };
9179             }
9180             
9181             if(s.width && s.width != 'auto'){
9182                 w = parseFloat(s.width);
9183                 if(me.isBorderBox()){
9184                    w -= me.getFrameWidth('lr');
9185                 }
9186             }
9187             
9188             if(s.height && s.height != 'auto'){
9189                 h = parseFloat(s.height);
9190                 if(me.isBorderBox()){
9191                    h -= me.getFrameWidth('tb');
9192                 }
9193             }
9194             
9195             return {width: w || me.getWidth(true), height: h || me.getHeight(true)};
9196         },
9197
9198         
9199         getSize : function(contentSize){
9200             return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
9201         },
9202
9203         
9204         repaint : function(){
9205             var dom = this.dom;
9206             this.addCls(Ext.baseCSSPrefix + 'repaint');
9207             setTimeout(function(){
9208                 Ext.fly(dom).removeCls(Ext.baseCSSPrefix + 'repaint');
9209             }, 1);
9210             return this;
9211         },
9212
9213         
9214         selectable : function() {
9215             var me = this;
9216             me.dom.unselectable = "off";
9217             
9218             me.on('selectstart', function (e) {
9219                 e.stopPropagation();
9220                 return true;
9221             });
9222             me.applyStyles("-moz-user-select: text; -khtml-user-select: text;");
9223             me.removeCls(Ext.baseCSSPrefix + 'unselectable');
9224             return me;
9225         },
9226
9227         
9228         unselectable : function(){
9229             var me = this;
9230             me.dom.unselectable = "on";
9231
9232             me.swallowEvent("selectstart", true);
9233             me.applyStyles("-moz-user-select:-moz-none;-khtml-user-select:none;");
9234             me.addCls(Ext.baseCSSPrefix + 'unselectable');
9235
9236             return me;
9237         },
9238
9239         
9240         getMargin : function(side){
9241             var me = this,
9242                 hash = {t:"top", l:"left", r:"right", b: "bottom"},
9243                 o = {},
9244                 key;
9245
9246             if (!side) {
9247                 for (key in me.margins){
9248                     o[hash[key]] = parseFloat(me.getStyle(me.margins[key])) || 0;
9249                 }
9250                 return o;
9251             } else {
9252                 return me.addStyles.call(me, side, me.margins);
9253             }
9254         }
9255     });
9256 })();
9257
9258
9259 Ext.Element.VISIBILITY = 1;
9260
9261 Ext.Element.DISPLAY = 2;
9262
9263
9264 Ext.Element.OFFSETS = 3;
9265
9266
9267 Ext.Element.ASCLASS = 4;
9268
9269
9270 Ext.Element.visibilityCls = Ext.baseCSSPrefix + 'hide-nosize';
9271
9272 Ext.Element.addMethods(function(){
9273     var El = Ext.Element,
9274         OPACITY = "opacity",
9275         VISIBILITY = "visibility",
9276         DISPLAY = "display",
9277         HIDDEN = "hidden",
9278         OFFSETS = "offsets",
9279         ASCLASS = "asclass",
9280         NONE = "none",
9281         NOSIZE = 'nosize',
9282         ORIGINALDISPLAY = 'originalDisplay',
9283         VISMODE = 'visibilityMode',
9284         ISVISIBLE = 'isVisible',
9285         data = El.data,
9286         getDisplay = function(dom){
9287             var d = data(dom, ORIGINALDISPLAY);
9288             if(d === undefined){
9289                 data(dom, ORIGINALDISPLAY, d = '');
9290             }
9291             return d;
9292         },
9293         getVisMode = function(dom){
9294             var m = data(dom, VISMODE);
9295             if(m === undefined){
9296                 data(dom, VISMODE, m = 1);
9297             }
9298             return m;
9299         };
9300
9301     return {
9302         
9303         originalDisplay : "",
9304         visibilityMode : 1,
9305
9306         
9307         setVisibilityMode : function(visMode){
9308             data(this.dom, VISMODE, visMode);
9309             return this;
9310         },
9311
9312         
9313         isVisible : function() {
9314             var me = this,
9315                 dom = me.dom,
9316                 visible = data(dom, ISVISIBLE);
9317
9318             if(typeof visible == 'boolean'){ 
9319                 return visible;
9320             }
9321             
9322             visible = !me.isStyle(VISIBILITY, HIDDEN) &&
9323                       !me.isStyle(DISPLAY, NONE) &&
9324                       !((getVisMode(dom) == El.ASCLASS) && me.hasCls(me.visibilityCls || El.visibilityCls));
9325
9326             data(dom, ISVISIBLE, visible);
9327             return visible;
9328         },
9329
9330         
9331         setVisible : function(visible, animate){
9332             var me = this, isDisplay, isVisibility, isOffsets, isNosize,
9333                 dom = me.dom,
9334                 visMode = getVisMode(dom);
9335
9336
9337             
9338             if (typeof animate == 'string'){
9339                 switch (animate) {
9340                     case DISPLAY:
9341                         visMode = El.DISPLAY;
9342                         break;
9343                     case VISIBILITY:
9344                         visMode = El.VISIBILITY;
9345                         break;
9346                     case OFFSETS:
9347                         visMode = El.OFFSETS;
9348                         break;
9349                     case NOSIZE:
9350                     case ASCLASS:
9351                         visMode = El.ASCLASS;
9352                         break;
9353                 }
9354                 me.setVisibilityMode(visMode);
9355                 animate = false;
9356             }
9357
9358             if (!animate || !me.anim) {
9359                 if(visMode == El.ASCLASS ){
9360
9361                     me[visible?'removeCls':'addCls'](me.visibilityCls || El.visibilityCls);
9362
9363                 } else if (visMode == El.DISPLAY){
9364
9365                     return me.setDisplayed(visible);
9366
9367                 } else if (visMode == El.OFFSETS){
9368
9369                     if (!visible){
9370                         
9371                         if (!me.hideModeStyles) {
9372                             me.hideModeStyles = {
9373                                 position: me.getStyle('position'),
9374                                 top: me.getStyle('top'),
9375                                 left: me.getStyle('left')
9376                             };
9377                         }
9378                         me.applyStyles({position: 'absolute', top: '-10000px', left: '-10000px'});
9379                     }
9380
9381                     
9382                     
9383                     else if (me.hideModeStyles) {
9384                         me.applyStyles(me.hideModeStyles || {position: '', top: '', left: ''});
9385                         delete me.hideModeStyles;
9386                     }
9387
9388                 }else{
9389                     me.fixDisplay();
9390                     
9391                     dom.style.visibility = visible ? '' : HIDDEN;
9392                 }
9393             }else{
9394                 
9395                 if(visible){
9396                     me.setOpacity(0.01);
9397                     me.setVisible(true);
9398                 }
9399                 if (!Ext.isObject(animate)) {
9400                     animate = {
9401                         duration: 350,
9402                         easing: 'ease-in'
9403                     };
9404                 }
9405                 me.animate(Ext.applyIf({
9406                     callback: function() {
9407                         visible || me.setVisible(false).setOpacity(1);
9408                     },
9409                     to: {
9410                         opacity: (visible) ? 1 : 0
9411                     }
9412                 }, animate));
9413             }
9414             data(dom, ISVISIBLE, visible);  
9415             return me;
9416         },
9417
9418
9419         
9420         hasMetrics  : function(){
9421             var dom = this.dom;
9422             return this.isVisible() || (getVisMode(dom) == El.OFFSETS) || (getVisMode(dom) == El.VISIBILITY);
9423         },
9424
9425         
9426         toggle : function(animate){
9427             var me = this;
9428             me.setVisible(!me.isVisible(), me.anim(animate));
9429             return me;
9430         },
9431
9432         
9433         setDisplayed : function(value) {
9434             if(typeof value == "boolean"){
9435                value = value ? getDisplay(this.dom) : NONE;
9436             }
9437             this.setStyle(DISPLAY, value);
9438             return this;
9439         },
9440
9441         
9442         fixDisplay : function(){
9443             var me = this;
9444             if (me.isStyle(DISPLAY, NONE)) {
9445                 me.setStyle(VISIBILITY, HIDDEN);
9446                 me.setStyle(DISPLAY, getDisplay(this.dom)); 
9447                 if (me.isStyle(DISPLAY, NONE)) { 
9448                     me.setStyle(DISPLAY, "block");
9449                 }
9450             }
9451         },
9452
9453         
9454         hide : function(animate){
9455             
9456             if (typeof animate == 'string'){
9457                 this.setVisible(false, animate);
9458                 return this;
9459             }
9460             this.setVisible(false, this.anim(animate));
9461             return this;
9462         },
9463
9464         
9465         show : function(animate){
9466             
9467             if (typeof animate == 'string'){
9468                 this.setVisible(true, animate);
9469                 return this;
9470             }
9471             this.setVisible(true, this.anim(animate));
9472             return this;
9473         }
9474     };
9475 }());
9476
9477 Ext.applyIf(Ext.Element.prototype, {
9478     
9479     animate: function(config) {
9480         var me = this;
9481         if (!me.id) {
9482             me = Ext.get(me.dom);
9483         }
9484         if (Ext.fx.Manager.hasFxBlock(me.id)) {
9485             return me;
9486         }
9487         Ext.fx.Manager.queueFx(Ext.create('Ext.fx.Anim', me.anim(config)));
9488         return this;
9489     },
9490
9491     
9492     anim: function(config) {
9493         if (!Ext.isObject(config)) {
9494             return (config) ? {} : false;
9495         }
9496
9497         var me = this,
9498             duration = config.duration || Ext.fx.Anim.prototype.duration,
9499             easing = config.easing || 'ease',
9500             animConfig;
9501
9502         if (config.stopAnimation) {
9503             me.stopAnimation();
9504         }
9505
9506         Ext.applyIf(config, Ext.fx.Manager.getFxDefaults(me.id));
9507
9508         
9509         Ext.fx.Manager.setFxDefaults(me.id, {
9510             delay: 0
9511         });
9512
9513         animConfig = {
9514             target: me,
9515             remove: config.remove,
9516             alternate: config.alternate || false,
9517             duration: duration,
9518             easing: easing,
9519             callback: config.callback,
9520             listeners: config.listeners,
9521             iterations: config.iterations || 1,
9522             scope: config.scope,
9523             block: config.block,
9524             concurrent: config.concurrent,
9525             delay: config.delay || 0,
9526             paused: true,
9527             keyframes: config.keyframes,
9528             from: config.from || {},
9529             to: Ext.apply({}, config)
9530         };
9531         Ext.apply(animConfig.to, config.to);
9532
9533         
9534         delete animConfig.to.to;
9535         delete animConfig.to.from;
9536         delete animConfig.to.remove;
9537         delete animConfig.to.alternate;
9538         delete animConfig.to.keyframes;
9539         delete animConfig.to.iterations;
9540         delete animConfig.to.listeners;
9541         delete animConfig.to.target;
9542         delete animConfig.to.paused;
9543         delete animConfig.to.callback;
9544         delete animConfig.to.scope;
9545         delete animConfig.to.duration;
9546         delete animConfig.to.easing;
9547         delete animConfig.to.concurrent;
9548         delete animConfig.to.block;
9549         delete animConfig.to.stopAnimation;
9550         delete animConfig.to.delay;
9551         return animConfig;
9552     },
9553
9554     
9555     slideIn: function(anchor, obj, slideOut) {
9556         var me = this,
9557             elStyle = me.dom.style,
9558             beforeAnim, wrapAnim;
9559
9560         anchor = anchor || "t";
9561         obj = obj || {};
9562
9563         beforeAnim = function() {
9564             var animScope = this,
9565                 listeners = obj.listeners,
9566                 box, position, restoreSize, wrap, anim;
9567
9568             if (!slideOut) {
9569                 me.fixDisplay();
9570             }
9571
9572             box = me.getBox();
9573             if ((anchor == 't' || anchor == 'b') && box.height === 0) {
9574                 box.height = me.dom.scrollHeight;
9575             }
9576             else if ((anchor == 'l' || anchor == 'r') && box.width === 0) {
9577                 box.width = me.dom.scrollWidth;
9578             }
9579
9580             position = me.getPositioning();
9581             me.setSize(box.width, box.height);
9582
9583             wrap = me.wrap({
9584                 style: {
9585                     visibility: slideOut ? 'visible' : 'hidden'
9586                 }
9587             });
9588             wrap.setPositioning(position);
9589             if (wrap.isStyle('position', 'static')) {
9590                 wrap.position('relative');
9591             }
9592             me.clearPositioning('auto');
9593             wrap.clip();
9594
9595             
9596             
9597             
9598             me.setStyle({
9599                 visibility: '',
9600                 position: 'absolute'
9601             });
9602             if (slideOut) {
9603                 wrap.setSize(box.width, box.height);
9604             }
9605
9606             switch (anchor) {
9607                 case 't':
9608                     anim = {
9609                         from: {
9610                             width: box.width + 'px',
9611                             height: '0px'
9612                         },
9613                         to: {
9614                             width: box.width + 'px',
9615                             height: box.height + 'px'
9616                         }
9617                     };
9618                     elStyle.bottom = '0px';
9619                     break;
9620                 case 'l':
9621                     anim = {
9622                         from: {
9623                             width: '0px',
9624                             height: box.height + 'px'
9625                         },
9626                         to: {
9627                             width: box.width + 'px',
9628                             height: box.height + 'px'
9629                         }
9630                     };
9631                     elStyle.right = '0px';
9632                     break;
9633                 case 'r':
9634                     anim = {
9635                         from: {
9636                             x: box.x + box.width,
9637                             width: '0px',
9638                             height: box.height + 'px'
9639                         },
9640                         to: {
9641                             x: box.x,
9642                             width: box.width + 'px',
9643                             height: box.height + 'px'
9644                         }
9645                     };
9646                     break;
9647                 case 'b':
9648                     anim = {
9649                         from: {
9650                             y: box.y + box.height,
9651                             width: box.width + 'px',
9652                             height: '0px'
9653                         },
9654                         to: {
9655                             y: box.y,
9656                             width: box.width + 'px',
9657                             height: box.height + 'px'
9658                         }
9659                     };
9660                     break;
9661                 case 'tl':
9662                     anim = {
9663                         from: {
9664                             x: box.x,
9665                             y: box.y,
9666                             width: '0px',
9667                             height: '0px'
9668                         },
9669                         to: {
9670                             width: box.width + 'px',
9671                             height: box.height + 'px'
9672                         }
9673                     };
9674                     elStyle.bottom = '0px';
9675                     elStyle.right = '0px';
9676                     break;
9677                 case 'bl':
9678                     anim = {
9679                         from: {
9680                             x: box.x + box.width,
9681                             width: '0px',
9682                             height: '0px'
9683                         },
9684                         to: {
9685                             x: box.x,
9686                             width: box.width + 'px',
9687                             height: box.height + 'px'
9688                         }
9689                     };
9690                     elStyle.right = '0px';
9691                     break;
9692                 case 'br':
9693                     anim = {
9694                         from: {
9695                             x: box.x + box.width,
9696                             y: box.y + box.height,
9697                             width: '0px',
9698                             height: '0px'
9699                         },
9700                         to: {
9701                             x: box.x,
9702                             y: box.y,
9703                             width: box.width + 'px',
9704                             height: box.height + 'px'
9705                         }
9706                     };
9707                     break;
9708                 case 'tr':
9709                     anim = {
9710                         from: {
9711                             y: box.y + box.height,
9712                             width: '0px',
9713                             height: '0px'
9714                         },
9715                         to: {
9716                             y: box.y,
9717                             width: box.width + 'px',
9718                             height: box.height + 'px'
9719                         }
9720                     };
9721                     elStyle.bottom = '0px';
9722                     break;
9723             }
9724
9725             wrap.show();
9726             wrapAnim = Ext.apply({}, obj);
9727             delete wrapAnim.listeners;
9728             wrapAnim = Ext.create('Ext.fx.Anim', Ext.applyIf(wrapAnim, {
9729                 target: wrap,
9730                 duration: 500,
9731                 easing: 'ease-out',
9732                 from: slideOut ? anim.to : anim.from,
9733                 to: slideOut ? anim.from : anim.to
9734             }));
9735
9736             
9737             wrapAnim.on('afteranimate', function() {
9738                 if (slideOut) {
9739                     me.setPositioning(position);
9740                     if (obj.useDisplay) {
9741                         me.setDisplayed(false);
9742                     } else {
9743                         me.hide();
9744                     }
9745                 }
9746                 else {
9747                     me.clearPositioning();
9748                     me.setPositioning(position);
9749                 }
9750                 if (wrap.dom) {
9751                     wrap.dom.parentNode.insertBefore(me.dom, wrap.dom);
9752                     wrap.remove();
9753                 }
9754                 me.setSize(box.width, box.height);
9755                 animScope.end();
9756             });
9757             
9758             if (listeners) {
9759                 wrapAnim.on(listeners);
9760             }
9761         };
9762
9763         me.animate({
9764             duration: obj.duration ? obj.duration * 2 : 1000,
9765             listeners: {
9766                 beforeanimate: {
9767                     fn: beforeAnim
9768                 },
9769                 afteranimate: {
9770                     fn: function() {
9771                         if (wrapAnim && wrapAnim.running) {
9772                             wrapAnim.end();
9773                         }
9774                     }
9775                 }
9776             }
9777         });
9778         return me;
9779     },
9780
9781
9782     
9783     slideOut: function(anchor, o) {
9784         return this.slideIn(anchor, o, true);
9785     },
9786
9787     
9788     puff: function(obj) {
9789         var me = this,
9790             beforeAnim;
9791         obj = Ext.applyIf(obj || {}, {
9792             easing: 'ease-out',
9793             duration: 500,
9794             useDisplay: false
9795         });
9796
9797         beforeAnim = function() {
9798             me.clearOpacity();
9799             me.show();
9800
9801             var box = me.getBox(),
9802                 fontSize = me.getStyle('fontSize'),
9803                 position = me.getPositioning();
9804             this.to = {
9805                 width: box.width * 2,
9806                 height: box.height * 2,
9807                 x: box.x - (box.width / 2),
9808                 y: box.y - (box.height /2),
9809                 opacity: 0,
9810                 fontSize: '200%'
9811             };
9812             this.on('afteranimate',function() {
9813                 if (me.dom) {
9814                     if (obj.useDisplay) {
9815                         me.setDisplayed(false);
9816                     } else {
9817                         me.hide();
9818                     }
9819                     me.clearOpacity();
9820                     me.setPositioning(position);
9821                     me.setStyle({fontSize: fontSize});
9822                 }
9823             });
9824         };
9825
9826         me.animate({
9827             duration: obj.duration,
9828             easing: obj.easing,
9829             listeners: {
9830                 beforeanimate: {
9831                     fn: beforeAnim
9832                 }
9833             }
9834         });
9835         return me;
9836     },
9837
9838     
9839     switchOff: function(obj) {
9840         var me = this,
9841             beforeAnim;
9842
9843         obj = Ext.applyIf(obj || {}, {
9844             easing: 'ease-in',
9845             duration: 500,
9846             remove: false,
9847             useDisplay: false
9848         });
9849
9850         beforeAnim = function() {
9851             var animScope = this,
9852                 size = me.getSize(),
9853                 xy = me.getXY(),
9854                 keyframe, position;
9855             me.clearOpacity();
9856             me.clip();
9857             position = me.getPositioning();
9858
9859             keyframe = Ext.create('Ext.fx.Animator', {
9860                 target: me,
9861                 duration: obj.duration,
9862                 easing: obj.easing,
9863                 keyframes: {
9864                     33: {
9865                         opacity: 0.3
9866                     },
9867                     66: {
9868                         height: 1,
9869                         y: xy[1] + size.height / 2
9870                     },
9871                     100: {
9872                         width: 1,
9873                         x: xy[0] + size.width / 2
9874                     }
9875                 }
9876             });
9877             keyframe.on('afteranimate', function() {
9878                 if (obj.useDisplay) {
9879                     me.setDisplayed(false);
9880                 } else {
9881                     me.hide();
9882                 }
9883                 me.clearOpacity();
9884                 me.setPositioning(position);
9885                 me.setSize(size);
9886                 animScope.end();
9887             });
9888         };
9889         me.animate({
9890             duration: (obj.duration * 2),
9891             listeners: {
9892                 beforeanimate: {
9893                     fn: beforeAnim
9894                 }
9895             }
9896         });
9897         return me;
9898     },
9899
9900     
9901     frame : function(color, count, obj){
9902         var me = this,
9903             beforeAnim;
9904
9905         color = color || '#C3DAF9';
9906         count = count || 1;
9907         obj = obj || {};
9908
9909         beforeAnim = function() {
9910             me.show();
9911             var animScope = this,
9912                 box = me.getBox(),
9913                 proxy = Ext.getBody().createChild({
9914                     style: {
9915                         position : 'absolute',
9916                         'pointer-events': 'none',
9917                         'z-index': 35000,
9918                         border : '0px solid ' + color
9919                     }
9920                 }),
9921                 proxyAnim;
9922             proxyAnim = Ext.create('Ext.fx.Anim', {
9923                 target: proxy,
9924                 duration: obj.duration || 1000,
9925                 iterations: count,
9926                 from: {
9927                     top: box.y,
9928                     left: box.x,
9929                     borderWidth: 0,
9930                     opacity: 1,
9931                     height: box.height,
9932                     width: box.width
9933                 },
9934                 to: {
9935                     top: box.y - 20,
9936                     left: box.x - 20,
9937                     borderWidth: 10,
9938                     opacity: 0,
9939                     height: box.height + 40,
9940                     width: box.width + 40
9941                 }
9942             });
9943             proxyAnim.on('afteranimate', function() {
9944                 proxy.remove();
9945                 animScope.end();
9946             });
9947         };
9948
9949         me.animate({
9950             duration: (obj.duration * 2) || 2000,
9951             listeners: {
9952                 beforeanimate: {
9953                     fn: beforeAnim
9954                 }
9955             }
9956         });
9957         return me;
9958     },
9959
9960     
9961     ghost: function(anchor, obj) {
9962         var me = this,
9963             beforeAnim;
9964
9965         anchor = anchor || "b";
9966         beforeAnim = function() {
9967             var width = me.getWidth(),
9968                 height = me.getHeight(),
9969                 xy = me.getXY(),
9970                 position = me.getPositioning(),
9971                 to = {
9972                     opacity: 0
9973                 };
9974             switch (anchor) {
9975                 case 't':
9976                     to.y = xy[1] - height;
9977                     break;
9978                 case 'l':
9979                     to.x = xy[0] - width;
9980                     break;
9981                 case 'r':
9982                     to.x = xy[0] + width;
9983                     break;
9984                 case 'b':
9985                     to.y = xy[1] + height;
9986                     break;
9987                 case 'tl':
9988                     to.x = xy[0] - width;
9989                     to.y = xy[1] - height;
9990                     break;
9991                 case 'bl':
9992                     to.x = xy[0] - width;
9993                     to.y = xy[1] + height;
9994                     break;
9995                 case 'br':
9996                     to.x = xy[0] + width;
9997                     to.y = xy[1] + height;
9998                     break;
9999                 case 'tr':
10000                     to.x = xy[0] + width;
10001                     to.y = xy[1] - height;
10002                     break;
10003             }
10004             this.to = to;
10005             this.on('afteranimate', function () {
10006                 if (me.dom) {
10007                     me.hide();
10008                     me.clearOpacity();
10009                     me.setPositioning(position);
10010                 }
10011             });
10012         };
10013
10014         me.animate(Ext.applyIf(obj || {}, {
10015             duration: 500,
10016             easing: 'ease-out',
10017             listeners: {
10018                 beforeanimate: {
10019                     fn: beforeAnim
10020                 }
10021             }
10022         }));
10023         return me;
10024     },
10025
10026     
10027     highlight: function(color, o) {
10028         var me = this,
10029             dom = me.dom,
10030             from = {},
10031             restore, to, attr, lns, event, fn;
10032
10033         o = o || {};
10034         lns = o.listeners || {};
10035         attr = o.attr || 'backgroundColor';
10036         from[attr] = color || 'ffff9c';
10037
10038         if (!o.to) {
10039             to = {};
10040             to[attr] = o.endColor || me.getColor(attr, 'ffffff', '');
10041         }
10042         else {
10043             to = o.to;
10044         }
10045
10046         
10047         o.listeners = Ext.apply(Ext.apply({}, lns), {
10048             beforeanimate: function() {
10049                 restore = dom.style[attr];
10050                 me.clearOpacity();
10051                 me.show();
10052
10053                 event = lns.beforeanimate;
10054                 if (event) {
10055                     fn = event.fn || event;
10056                     return fn.apply(event.scope || lns.scope || window, arguments);
10057                 }
10058             },
10059             afteranimate: function() {
10060                 if (dom) {
10061                     dom.style[attr] = restore;
10062                 }
10063
10064                 event = lns.afteranimate;
10065                 if (event) {
10066                     fn = event.fn || event;
10067                     fn.apply(event.scope || lns.scope || window, arguments);
10068                 }
10069             }
10070         });
10071
10072         me.animate(Ext.apply({}, o, {
10073             duration: 1000,
10074             easing: 'ease-in',
10075             from: from,
10076             to: to
10077         }));
10078         return me;
10079     },
10080
10081    
10082     pause: function(ms) {
10083         var me = this;
10084         Ext.fx.Manager.setFxDefaults(me.id, {
10085             delay: ms
10086         });
10087         return me;
10088     },
10089
10090     
10091     fadeIn: function(o) {
10092         this.animate(Ext.apply({}, o, {
10093             opacity: 1
10094         }));
10095         return this;
10096     },
10097
10098     
10099     fadeOut: function(o) {
10100         this.animate(Ext.apply({}, o, {
10101             opacity: 0
10102         }));
10103         return this;
10104     },
10105
10106     
10107     scale: function(w, h, o) {
10108         this.animate(Ext.apply({}, o, {
10109             width: w,
10110             height: h
10111         }));
10112         return this;
10113     },
10114
10115     
10116     shift: function(config) {
10117         this.animate(config);
10118         return this;
10119     }
10120 });
10121
10122
10123 Ext.applyIf(Ext.Element, {
10124     unitRe: /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
10125     camelRe: /(-[a-z])/gi,
10126     opacityRe: /alpha\(opacity=(.*)\)/i,
10127     cssRe: /([a-z0-9-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*);?/gi,
10128     propertyCache: {},
10129     defaultUnit : "px",
10130     borders: {l: 'border-left-width', r: 'border-right-width', t: 'border-top-width', b: 'border-bottom-width'},
10131     paddings: {l: 'padding-left', r: 'padding-right', t: 'padding-top', b: 'padding-bottom'},
10132     margins: {l: 'margin-left', r: 'margin-right', t: 'margin-top', b: 'margin-bottom'},
10133
10134     
10135     addUnits : Ext.Element.prototype.addUnits,
10136
10137     
10138     parseBox : function(box) {
10139         if (Ext.isObject(box)) {
10140             return {
10141                 top: box.top || 0,
10142                 right: box.right || 0,
10143                 bottom: box.bottom || 0,
10144                 left: box.left || 0
10145             };
10146         } else {
10147             if (typeof box != 'string') {
10148                 box = box.toString();
10149             }
10150             var parts  = box.split(' '),
10151                 ln = parts.length;
10152     
10153             if (ln == 1) {
10154                 parts[1] = parts[2] = parts[3] = parts[0];
10155             }
10156             else if (ln == 2) {
10157                 parts[2] = parts[0];
10158                 parts[3] = parts[1];
10159             }
10160             else if (ln == 3) {
10161                 parts[3] = parts[1];
10162             }
10163     
10164             return {
10165                 top   :parseFloat(parts[0]) || 0,
10166                 right :parseFloat(parts[1]) || 0,
10167                 bottom:parseFloat(parts[2]) || 0,
10168                 left  :parseFloat(parts[3]) || 0
10169             };
10170         }
10171         
10172     },
10173     
10174     
10175     unitizeBox : function(box, units) {
10176         var A = this.addUnits,
10177             B = this.parseBox(box);
10178             
10179         return A(B.top, units) + ' ' +
10180                A(B.right, units) + ' ' +
10181                A(B.bottom, units) + ' ' +
10182                A(B.left, units);
10183         
10184     },
10185
10186     
10187     camelReplaceFn : function(m, a) {
10188         return a.charAt(1).toUpperCase();
10189     },
10190
10191     
10192     normalize : function(prop) {
10193         if (prop == 'float') {
10194             prop = Ext.supports.Float ? 'cssFloat' : 'styleFloat';
10195         }
10196         return this.propertyCache[prop] || (this.propertyCache[prop] = prop.replace(this.camelRe, this.camelReplaceFn));
10197     },
10198
10199     
10200     getDocumentHeight: function() {
10201         return Math.max(!Ext.isStrict ? document.body.scrollHeight : document.documentElement.scrollHeight, this.getViewportHeight());
10202     },
10203
10204     
10205     getDocumentWidth: function() {
10206         return Math.max(!Ext.isStrict ? document.body.scrollWidth : document.documentElement.scrollWidth, this.getViewportWidth());
10207     },
10208
10209     
10210     getViewportHeight: function(){
10211         return window.innerHeight;
10212     },
10213
10214     
10215     getViewportWidth : function() {
10216         return window.innerWidth;
10217     },
10218
10219     
10220     getViewSize : function() {
10221         return {
10222             width: window.innerWidth,
10223             height: window.innerHeight
10224         };
10225     },
10226
10227     
10228     getOrientation : function() {
10229         if (Ext.supports.OrientationChange) {
10230             return (window.orientation == 0) ? 'portrait' : 'landscape';
10231         }
10232         
10233         return (window.innerHeight > window.innerWidth) ? 'portrait' : 'landscape';
10234     },
10235
10236     
10237     fromPoint: function(x, y) {
10238         return Ext.get(document.elementFromPoint(x, y));
10239     },
10240     
10241     
10242     parseStyles: function(styles){
10243         var out = {},
10244             cssRe = this.cssRe,
10245             matches;
10246             
10247         if (styles) {
10248             
10249             
10250             
10251             
10252             cssRe.lastIndex = 0;
10253             while ((matches = cssRe.exec(styles))) {
10254                 out[matches[1]] = matches[2];
10255             }
10256         }
10257         return out;
10258     }
10259 });
10260
10261
10262 Ext.CompositeElementLite = function(els, root){
10263     
10264     this.elements = [];
10265     this.add(els, root);
10266     this.el = new Ext.Element.Flyweight();
10267 };
10268
10269 Ext.CompositeElementLite.prototype = {
10270     isComposite: true,
10271
10272     
10273     getElement : function(el){
10274         
10275         var e = this.el;
10276         e.dom = el;
10277         e.id = el.id;
10278         return e;
10279     },
10280
10281     
10282     transformElement : function(el){
10283         return Ext.getDom(el);
10284     },
10285
10286     
10287     getCount : function(){
10288         return this.elements.length;
10289     },
10290     
10291     add : function(els, root){
10292         var me = this,
10293             elements = me.elements;
10294         if(!els){
10295             return this;
10296         }
10297         if(typeof els == "string"){
10298             els = Ext.Element.selectorFunction(els, root);
10299         }else if(els.isComposite){
10300             els = els.elements;
10301         }else if(!Ext.isIterable(els)){
10302             els = [els];
10303         }
10304
10305         for(var i = 0, len = els.length; i < len; ++i){
10306             elements.push(me.transformElement(els[i]));
10307         }
10308         return me;
10309     },
10310
10311     invoke : function(fn, args){
10312         var me = this,
10313             els = me.elements,
10314             len = els.length,
10315             e,
10316             i;
10317
10318         for(i = 0; i < len; i++) {
10319             e = els[i];
10320             if(e){
10321                 Ext.Element.prototype[fn].apply(me.getElement(e), args);
10322             }
10323         }
10324         return me;
10325     },
10326     
10327     item : function(index){
10328         var me = this,
10329             el = me.elements[index],
10330             out = null;
10331
10332         if(el){
10333             out = me.getElement(el);
10334         }
10335         return out;
10336     },
10337
10338     
10339     addListener : function(eventName, handler, scope, opt){
10340         var els = this.elements,
10341             len = els.length,
10342             i, e;
10343
10344         for(i = 0; i<len; i++) {
10345             e = els[i];
10346             if(e) {
10347                 Ext.EventManager.on(e, eventName, handler, scope || e, opt);
10348             }
10349         }
10350         return this;
10351     },
10352     
10353     each : function(fn, scope){
10354         var me = this,
10355             els = me.elements,
10356             len = els.length,
10357             i, e;
10358
10359         for(i = 0; i<len; i++) {
10360             e = els[i];
10361             if(e){
10362                 e = this.getElement(e);
10363                 if(fn.call(scope || e, e, me, i) === false){
10364                     break;
10365                 }
10366             }
10367         }
10368         return me;
10369     },
10370
10371     
10372     fill : function(els){
10373         var me = this;
10374         me.elements = [];
10375         me.add(els);
10376         return me;
10377     },
10378
10379     
10380     filter : function(selector){
10381         var els = [],
10382             me = this,
10383             fn = Ext.isFunction(selector) ? selector
10384                 : function(el){
10385                     return el.is(selector);
10386                 };
10387
10388         me.each(function(el, self, i) {
10389             if (fn(el, i) !== false) {
10390                 els[els.length] = me.transformElement(el);
10391             }
10392         });
10393
10394         me.elements = els;
10395         return me;
10396     },
10397
10398     
10399     indexOf : function(el){
10400         return Ext.Array.indexOf(this.elements, this.transformElement(el));
10401     },
10402
10403     
10404     replaceElement : function(el, replacement, domReplace){
10405         var index = !isNaN(el) ? el : this.indexOf(el),
10406             d;
10407         if(index > -1){
10408             replacement = Ext.getDom(replacement);
10409             if(domReplace){
10410                 d = this.elements[index];
10411                 d.parentNode.insertBefore(replacement, d);
10412                 Ext.removeNode(d);
10413             }
10414             Ext.Array.splice(this.elements, index, 1, replacement);
10415         }
10416         return this;
10417     },
10418
10419     
10420     clear : function(){
10421         this.elements = [];
10422     }
10423 };
10424
10425 Ext.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;
10426
10427
10428 Ext.CompositeElementLite.importElementMethods = function() {
10429     var fnName,
10430         ElProto = Ext.Element.prototype,
10431         CelProto = Ext.CompositeElementLite.prototype;
10432
10433     for (fnName in ElProto) {
10434         if (typeof ElProto[fnName] == 'function'){
10435             (function(fnName) {
10436                 CelProto[fnName] = CelProto[fnName] || function() {
10437                     return this.invoke(fnName, arguments);
10438                 };
10439             }).call(CelProto, fnName);
10440
10441         }
10442     }
10443 };
10444
10445 Ext.CompositeElementLite.importElementMethods();
10446
10447 if(Ext.DomQuery){
10448     Ext.Element.selectorFunction = Ext.DomQuery.select;
10449 }
10450
10451
10452 Ext.Element.select = function(selector, root){
10453     var els;
10454     if(typeof selector == "string"){
10455         els = Ext.Element.selectorFunction(selector, root);
10456     }else if(selector.length !== undefined){
10457         els = selector;
10458     }else{
10459     }
10460     return new Ext.CompositeElementLite(els);
10461 };
10462
10463 Ext.select = Ext.Element.select;
10464
10465
10466 Ext.util.DelayedTask = function(fn, scope, args) {
10467     var me = this,
10468         id,
10469         call = function() {
10470             clearInterval(id);
10471             id = null;
10472             fn.apply(scope, args || []);
10473         };
10474
10475     
10476     this.delay = function(delay, newFn, newScope, newArgs) {
10477         me.cancel();
10478         fn = newFn || fn;
10479         scope = newScope || scope;
10480         args = newArgs || args;
10481         id = setInterval(call, delay);
10482     };
10483
10484     
10485     this.cancel = function(){
10486         if (id) {
10487             clearInterval(id);
10488             id = null;
10489         }
10490     };
10491 };
10492 Ext.require('Ext.util.DelayedTask', function() {
10493
10494     Ext.util.Event = Ext.extend(Object, (function() {
10495         function createBuffered(handler, listener, o, scope) {
10496             listener.task = new Ext.util.DelayedTask();
10497             return function() {
10498                 listener.task.delay(o.buffer, handler, scope, Ext.Array.toArray(arguments));
10499             };
10500         }
10501
10502         function createDelayed(handler, listener, o, scope) {
10503             return function() {
10504                 var task = new Ext.util.DelayedTask();
10505                 if (!listener.tasks) {
10506                     listener.tasks = [];
10507                 }
10508                 listener.tasks.push(task);
10509                 task.delay(o.delay || 10, handler, scope, Ext.Array.toArray(arguments));
10510             };
10511         }
10512
10513         function createSingle(handler, listener, o, scope) {
10514             return function() {
10515                 listener.ev.removeListener(listener.fn, scope);
10516                 return handler.apply(scope, arguments);
10517             };
10518         }
10519
10520         return {
10521             isEvent: true,
10522
10523             constructor: function(observable, name) {
10524                 this.name = name;
10525                 this.observable = observable;
10526                 this.listeners = [];
10527             },
10528
10529             addListener: function(fn, scope, options) {
10530                 var me = this,
10531                     listener;
10532                     scope = scope || me.observable;
10533
10534
10535                 if (!me.isListening(fn, scope)) {
10536                     listener = me.createListener(fn, scope, options);
10537                     if (me.firing) {
10538                         
10539                         me.listeners = me.listeners.slice(0);
10540                     }
10541                     me.listeners.push(listener);
10542                 }
10543             },
10544
10545             createListener: function(fn, scope, o) {
10546                 o = o || {};
10547                 scope = scope || this.observable;
10548
10549                 var listener = {
10550                         fn: fn,
10551                         scope: scope,
10552                         o: o,
10553                         ev: this
10554                     },
10555                     handler = fn;
10556
10557                 
10558                 
10559                 if (o.single) {
10560                     handler = createSingle(handler, listener, o, scope);
10561                 }
10562                 if (o.delay) {
10563                     handler = createDelayed(handler, listener, o, scope);
10564                 }
10565                 if (o.buffer) {
10566                     handler = createBuffered(handler, listener, o, scope);
10567                 }
10568
10569                 listener.fireFn = handler;
10570                 return listener;
10571             },
10572
10573             findListener: function(fn, scope) {
10574                 var listeners = this.listeners,
10575                 i = listeners.length,
10576                 listener,
10577                 s;
10578
10579                 while (i--) {
10580                     listener = listeners[i];
10581                     if (listener) {
10582                         s = listener.scope;
10583                         if (listener.fn == fn && (s == scope || s == this.observable)) {
10584                             return i;
10585                         }
10586                     }
10587                 }
10588
10589                 return - 1;
10590             },
10591
10592             isListening: function(fn, scope) {
10593                 return this.findListener(fn, scope) !== -1;
10594             },
10595
10596             removeListener: function(fn, scope) {
10597                 var me = this,
10598                     index,
10599                     listener,
10600                     k;
10601                 index = me.findListener(fn, scope);
10602                 if (index != -1) {
10603                     listener = me.listeners[index];
10604
10605                     if (me.firing) {
10606                         me.listeners = me.listeners.slice(0);
10607                     }
10608
10609                     
10610                     if (listener.task) {
10611                         listener.task.cancel();
10612                         delete listener.task;
10613                     }
10614
10615                     
10616                     k = listener.tasks && listener.tasks.length;
10617                     if (k) {
10618                         while (k--) {
10619                             listener.tasks[k].cancel();
10620                         }
10621                         delete listener.tasks;
10622                     }
10623
10624                     
10625                     Ext.Array.erase(me.listeners, index, 1);
10626                     return true;
10627                 }
10628
10629                 return false;
10630             },
10631
10632             
10633             clearListeners: function() {
10634                 var listeners = this.listeners,
10635                     i = listeners.length;
10636
10637                 while (i--) {
10638                     this.removeListener(listeners[i].fn, listeners[i].scope);
10639                 }
10640             },
10641
10642             fire: function() {
10643                 var me = this,
10644                     listeners = me.listeners,
10645                     count = listeners.length,
10646                     i,
10647                     args,
10648                     listener;
10649
10650                 if (count > 0) {
10651                     me.firing = true;
10652                     for (i = 0; i < count; i++) {
10653                         listener = listeners[i];
10654                         args = arguments.length ? Array.prototype.slice.call(arguments, 0) : [];
10655                         if (listener.o) {
10656                             args.push(listener.o);
10657                         }
10658                         if (listener && listener.fireFn.apply(listener.scope || me.observable, args) === false) {
10659                             return (me.firing = false);
10660                         }
10661                     }
10662                 }
10663                 me.firing = false;
10664                 return true;
10665             }
10666         };
10667     })());
10668 });
10669
10670
10671 Ext.EventManager = {
10672
10673     
10674
10675     
10676     hasBoundOnReady: false,
10677
10678     
10679     hasFiredReady: false,
10680
10681     
10682     readyTimeout: null,
10683
10684     
10685     hasOnReadyStateChange: false,
10686
10687     
10688     readyEvent: new Ext.util.Event(),
10689
10690     
10691     checkReadyState: function(){
10692         var me = Ext.EventManager;
10693
10694         if(window.attachEvent){
10695             
10696             
10697             if (window != top) {
10698                 return false;
10699             }
10700             try{
10701                 document.documentElement.doScroll('left');
10702             }catch(e){
10703                 return false;
10704             }
10705             me.fireDocReady();
10706             return true;
10707         }
10708         if (document.readyState == 'complete') {
10709             me.fireDocReady();
10710             return true;
10711         }
10712         me.readyTimeout = setTimeout(arguments.callee, 2);
10713         return false;
10714     },
10715
10716     
10717     bindReadyEvent: function(){
10718         var me = Ext.EventManager;
10719         if (me.hasBoundOnReady) {
10720             return;
10721         }
10722
10723         if (document.addEventListener) {
10724             document.addEventListener('DOMContentLoaded', me.fireDocReady, false);
10725             
10726             window.addEventListener('load', me.fireDocReady, false);
10727         } else {
10728             
10729             if (!me.checkReadyState()) {
10730                 document.attachEvent('onreadystatechange', me.checkReadyState);
10731                 me.hasOnReadyStateChange = true;
10732             }
10733             
10734             window.attachEvent('onload', me.fireDocReady, false);
10735         }
10736         me.hasBoundOnReady = true;
10737     },
10738
10739     
10740     fireDocReady: function(){
10741         var me = Ext.EventManager;
10742
10743         
10744         if (!me.hasFiredReady) {
10745             me.hasFiredReady = true;
10746
10747             if (document.addEventListener) {
10748                 document.removeEventListener('DOMContentLoaded', me.fireDocReady, false);
10749                 window.removeEventListener('load', me.fireDocReady, false);
10750             } else {
10751                 if (me.readyTimeout !== null) {
10752                     clearTimeout(me.readyTimeout);
10753                 }
10754                 if (me.hasOnReadyStateChange) {
10755                     document.detachEvent('onreadystatechange', me.checkReadyState);
10756                 }
10757                 window.detachEvent('onload', me.fireDocReady);
10758             }
10759             Ext.supports.init();
10760         }
10761         if (!Ext.isReady) {
10762             Ext.isReady = true;
10763             me.onWindowUnload();
10764             me.readyEvent.fire();
10765         }
10766     },
10767
10768     
10769     onDocumentReady: function(fn, scope, options){
10770         options = options || {};
10771         var me = Ext.EventManager,
10772             readyEvent = me.readyEvent;
10773
10774         
10775         options.single = true;
10776
10777         
10778         if (Ext.isReady) {
10779             readyEvent.addListener(fn, scope, options);
10780             readyEvent.fire();
10781         } else {
10782             options.delay = options.delay || 1;
10783             readyEvent.addListener(fn, scope, options);
10784             me.bindReadyEvent();
10785         }
10786     },
10787
10788
10789     
10790
10791     
10792     stoppedMouseDownEvent: new Ext.util.Event(),
10793
10794     
10795     propRe: /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate|freezeEvent)$/,
10796
10797     
10798     getId : function(element) {
10799         var skipGarbageCollection = false,
10800             id;
10801
10802         element = Ext.getDom(element);
10803
10804         if (element === document || element === window) {
10805             id = element === document ? Ext.documentId : Ext.windowId;
10806         }
10807         else {
10808             id = Ext.id(element);
10809         }
10810         
10811         if (element && (element.getElementById || element.navigator)) {
10812             skipGarbageCollection = true;
10813         }
10814
10815         if (!Ext.cache[id]){
10816             Ext.Element.addToCache(new Ext.Element(element), id);
10817             if (skipGarbageCollection) {
10818                 Ext.cache[id].skipGarbageCollection = true;
10819             }
10820         }
10821         return id;
10822     },
10823
10824     
10825     prepareListenerConfig: function(element, config, isRemove){
10826         var me = this,
10827             propRe = me.propRe,
10828             key, value, args;
10829
10830         
10831         for (key in config) {
10832             if (config.hasOwnProperty(key)) {
10833                 
10834                 if (!propRe.test(key)) {
10835                     value = config[key];
10836                     
10837                     
10838                     if (Ext.isFunction(value)) {
10839                         
10840                         args = [element, key, value, config.scope, config];
10841                     } else {
10842                         
10843                         args = [element, key, value.fn, value.scope, value];
10844                     }
10845
10846                     if (isRemove === true) {
10847                         me.removeListener.apply(this, args);
10848                     } else {
10849                         me.addListener.apply(me, args);
10850                     }
10851                 }
10852             }
10853         }
10854     },
10855
10856     
10857     normalizeEvent: function(eventName, fn){
10858         if (/mouseenter|mouseleave/.test(eventName) && !Ext.supports.MouseEnterLeave) {
10859             if (fn) {
10860                 fn = Ext.Function.createInterceptor(fn, this.contains, this);
10861             }
10862             eventName = eventName == 'mouseenter' ? 'mouseover' : 'mouseout';
10863         } else if (eventName == 'mousewheel' && !Ext.supports.MouseWheel && !Ext.isOpera){
10864             eventName = 'DOMMouseScroll';
10865         }
10866         return {
10867             eventName: eventName,
10868             fn: fn
10869         };
10870     },
10871
10872     
10873     contains: function(event){
10874         var parent = event.browserEvent.currentTarget,
10875             child = this.getRelatedTarget(event);
10876
10877         if (parent && parent.firstChild) {
10878             while (child) {
10879                 if (child === parent) {
10880                     return false;
10881                 }
10882                 child = child.parentNode;
10883                 if (child && (child.nodeType != 1)) {
10884                     child = null;
10885                 }
10886             }
10887         }
10888         return true;
10889     },
10890
10891     
10892     addListener: function(element, eventName, fn, scope, options){
10893         
10894         if (typeof eventName !== 'string') {
10895             this.prepareListenerConfig(element, eventName);
10896             return;
10897         }
10898
10899         var dom = Ext.getDom(element),
10900             bind,
10901             wrap;
10902
10903
10904         
10905         options = options || {};
10906
10907         bind = this.normalizeEvent(eventName, fn);
10908         wrap = this.createListenerWrap(dom, eventName, bind.fn, scope, options);
10909
10910
10911         if (dom.attachEvent) {
10912             dom.attachEvent('on' + bind.eventName, wrap);
10913         } else {
10914             dom.addEventListener(bind.eventName, wrap, options.capture || false);
10915         }
10916
10917         if (dom == document && eventName == 'mousedown') {
10918             this.stoppedMouseDownEvent.addListener(wrap);
10919         }
10920
10921         
10922         this.getEventListenerCache(dom, eventName).push({
10923             fn: fn,
10924             wrap: wrap,
10925             scope: scope
10926         });
10927     },
10928
10929     
10930     removeListener : function(element, eventName, fn, scope) {
10931         
10932         if (typeof eventName !== 'string') {
10933             this.prepareListenerConfig(element, eventName, true);
10934             return;
10935         }
10936
10937         var dom = Ext.getDom(element),
10938             cache = this.getEventListenerCache(dom, eventName),
10939             bindName = this.normalizeEvent(eventName).eventName,
10940             i = cache.length, j,
10941             listener, wrap, tasks;
10942
10943
10944         while (i--) {
10945             listener = cache[i];
10946
10947             if (listener && (!fn || listener.fn == fn) && (!scope || listener.scope === scope)) {
10948                 wrap = listener.wrap;
10949
10950                 
10951                 if (wrap.task) {
10952                     clearTimeout(wrap.task);
10953                     delete wrap.task;
10954                 }
10955
10956                 
10957                 j = wrap.tasks && wrap.tasks.length;
10958                 if (j) {
10959                     while (j--) {
10960                         clearTimeout(wrap.tasks[j]);
10961                     }
10962                     delete wrap.tasks;
10963                 }
10964
10965                 if (dom.detachEvent) {
10966                     dom.detachEvent('on' + bindName, wrap);
10967                 } else {
10968                     dom.removeEventListener(bindName, wrap, false);
10969                 }
10970
10971                 if (wrap && dom == document && eventName == 'mousedown') {
10972                     this.stoppedMouseDownEvent.removeListener(wrap);
10973                 }
10974
10975                 
10976                 Ext.Array.erase(cache, i, 1);
10977             }
10978         }
10979     },
10980
10981     
10982     removeAll : function(element){
10983         var dom = Ext.getDom(element),
10984             cache, ev;
10985         if (!dom) {
10986             return;
10987         }
10988         cache = this.getElementEventCache(dom);
10989
10990         for (ev in cache) {
10991             if (cache.hasOwnProperty(ev)) {
10992                 this.removeListener(dom, ev);
10993             }
10994         }
10995         Ext.cache[dom.id].events = {};
10996     },
10997
10998     
10999     purgeElement : function(element, eventName) {
11000         var dom = Ext.getDom(element),
11001             i = 0, len;
11002
11003         if(eventName) {
11004             this.removeListener(dom, eventName);
11005         }
11006         else {
11007             this.removeAll(dom);
11008         }
11009
11010         if(dom && dom.childNodes) {
11011             for(len = element.childNodes.length; i < len; i++) {
11012                 this.purgeElement(element.childNodes[i], eventName);
11013             }
11014         }
11015     },
11016
11017     
11018     createListenerWrap : function(dom, ename, fn, scope, options) {
11019         options = options || {};
11020
11021         var f, gen;
11022
11023         return function wrap(e, args) {
11024             
11025             if (!gen) {
11026                 f = ['if(!Ext) {return;}'];
11027
11028                 if(options.buffer || options.delay || options.freezeEvent) {
11029                     f.push('e = new Ext.EventObjectImpl(e, ' + (options.freezeEvent ? 'true' : 'false' ) + ');');
11030                 } else {
11031                     f.push('e = Ext.EventObject.setEvent(e);');
11032                 }
11033
11034                 if (options.delegate) {
11035                     f.push('var t = e.getTarget("' + options.delegate + '", this);');
11036                     f.push('if(!t) {return;}');
11037                 } else {
11038                     f.push('var t = e.target;');
11039                 }
11040
11041                 if (options.target) {
11042                     f.push('if(e.target !== options.target) {return;}');
11043                 }
11044
11045                 if(options.stopEvent) {
11046                     f.push('e.stopEvent();');
11047                 } else {
11048                     if(options.preventDefault) {
11049                         f.push('e.preventDefault();');
11050                     }
11051                     if(options.stopPropagation) {
11052                         f.push('e.stopPropagation();');
11053                     }
11054                 }
11055
11056                 if(options.normalized === false) {
11057                     f.push('e = e.browserEvent;');
11058                 }
11059
11060                 if(options.buffer) {
11061                     f.push('(wrap.task && clearTimeout(wrap.task));');
11062                     f.push('wrap.task = setTimeout(function(){');
11063                 }
11064
11065                 if(options.delay) {
11066                     f.push('wrap.tasks = wrap.tasks || [];');
11067                     f.push('wrap.tasks.push(setTimeout(function(){');
11068                 }
11069
11070                 
11071                 f.push('fn.call(scope || dom, e, t, options);');
11072
11073                 if(options.single) {
11074                     f.push('Ext.EventManager.removeListener(dom, ename, fn, scope);');
11075                 }
11076
11077                 if(options.delay) {
11078                     f.push('}, ' + options.delay + '));');
11079                 }
11080
11081                 if(options.buffer) {
11082                     f.push('}, ' + options.buffer + ');');
11083                 }
11084
11085                 gen = Ext.functionFactory('e', 'options', 'fn', 'scope', 'ename', 'dom', 'wrap', 'args', f.join('\n'));
11086             }
11087
11088             gen.call(dom, e, options, fn, scope, ename, dom, wrap, args);
11089         };
11090     },
11091
11092     
11093     getEventListenerCache : function(element, eventName) {
11094         if (!element) {
11095             return [];
11096         }
11097
11098         var eventCache = this.getElementEventCache(element);
11099         return eventCache[eventName] || (eventCache[eventName] = []);
11100     },
11101
11102     
11103     getElementEventCache : function(element) {
11104         if (!element) {
11105             return {};
11106         }
11107         var elementCache = Ext.cache[this.getId(element)];
11108         return elementCache.events || (elementCache.events = {});
11109     },
11110
11111     
11112     mouseLeaveRe: /(mouseout|mouseleave)/,
11113     mouseEnterRe: /(mouseover|mouseenter)/,
11114
11115     
11116     stopEvent: function(event) {
11117         this.stopPropagation(event);
11118         this.preventDefault(event);
11119     },
11120
11121     
11122     stopPropagation: function(event) {
11123         event = event.browserEvent || event;
11124         if (event.stopPropagation) {
11125             event.stopPropagation();
11126         } else {
11127             event.cancelBubble = true;
11128         }
11129     },
11130
11131     
11132     preventDefault: function(event) {
11133         event = event.browserEvent || event;
11134         if (event.preventDefault) {
11135             event.preventDefault();
11136         } else {
11137             event.returnValue = false;
11138             
11139             try {
11140               
11141               if (event.ctrlKey || event.keyCode > 111 && event.keyCode < 124) {
11142                   event.keyCode = -1;
11143               }
11144             } catch (e) {
11145                 
11146             }
11147         }
11148     },
11149
11150     
11151     getRelatedTarget: function(event) {
11152         event = event.browserEvent || event;
11153         var target = event.relatedTarget;
11154         if (!target) {
11155             if (this.mouseLeaveRe.test(event.type)) {
11156                 target = event.toElement;
11157             } else if (this.mouseEnterRe.test(event.type)) {
11158                 target = event.fromElement;
11159             }
11160         }
11161         return this.resolveTextNode(target);
11162     },
11163
11164     
11165     getPageX: function(event) {
11166         return this.getXY(event)[0];
11167     },
11168
11169     
11170     getPageY: function(event) {
11171         return this.getXY(event)[1];
11172     },
11173
11174     
11175     getPageXY: function(event) {
11176         event = event.browserEvent || event;
11177         var x = event.pageX,
11178             y = event.pageY,
11179             doc = document.documentElement,
11180             body = document.body;
11181
11182         
11183         if (!x && x !== 0) {
11184             x = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
11185             y = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);
11186         }
11187         return [x, y];
11188     },
11189
11190     
11191     getTarget: function(event) {
11192         event = event.browserEvent || event;
11193         return this.resolveTextNode(event.target || event.srcElement);
11194     },
11195
11196     
11197     
11198     resolveTextNode: Ext.isGecko ?
11199         function(node) {
11200             if (!node) {
11201                 return;
11202             }
11203             
11204             var s = HTMLElement.prototype.toString.call(node);
11205             if (s == '[xpconnect wrapped native prototype]' || s == '[object XULElement]') {
11206                 return;
11207             }
11208                 return node.nodeType == 3 ? node.parentNode: node;
11209             }: function(node) {
11210                 return node && node.nodeType == 3 ? node.parentNode: node;
11211             },
11212
11213     
11214
11215     
11216     curWidth: 0,
11217     curHeight: 0,
11218
11219     
11220     onWindowResize: function(fn, scope, options){
11221         var resize = this.resizeEvent;
11222         if(!resize){
11223             this.resizeEvent = resize = new Ext.util.Event();
11224             this.on(window, 'resize', this.fireResize, this, {buffer: 100});
11225         }
11226         resize.addListener(fn, scope, options);
11227     },
11228
11229     
11230     fireResize: function(){
11231         var me = this,
11232             w = Ext.Element.getViewWidth(),
11233             h = Ext.Element.getViewHeight();
11234
11235          
11236          if(me.curHeight != h || me.curWidth != w){
11237              me.curHeight = h;
11238              me.curWidth = w;
11239              me.resizeEvent.fire(w, h);
11240          }
11241     },
11242
11243     
11244     removeResizeListener: function(fn, scope){
11245         if (this.resizeEvent) {
11246             this.resizeEvent.removeListener(fn, scope);
11247         }
11248     },
11249
11250     onWindowUnload: function() {
11251         var unload = this.unloadEvent;
11252         if (!unload) {
11253             this.unloadEvent = unload = new Ext.util.Event();
11254             this.addListener(window, 'unload', this.fireUnload, this);
11255         }
11256     },
11257
11258     
11259     fireUnload: function() {
11260         
11261         try {
11262             this.removeUnloadListener();
11263             
11264             if (Ext.isGecko3) {
11265                 var gridviews = Ext.ComponentQuery.query('gridview'),
11266                     i = 0,
11267                     ln = gridviews.length;
11268                 for (; i < ln; i++) {
11269                     gridviews[i].scrollToTop();
11270                 }
11271             }
11272             
11273             var el,
11274                 cache = Ext.cache;
11275             for (el in cache) {
11276                 if (cache.hasOwnProperty(el)) {
11277                     Ext.EventManager.removeAll(el);
11278                 }
11279             }
11280         } catch(e) {
11281         }
11282     },
11283
11284     
11285     removeUnloadListener: function(){
11286         if (this.unloadEvent) {
11287             this.removeListener(window, 'unload', this.fireUnload);
11288         }
11289     },
11290
11291     
11292     useKeyDown: Ext.isWebKit ?
11293                    parseInt(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1], 10) >= 525 :
11294                    !((Ext.isGecko && !Ext.isWindows) || Ext.isOpera),
11295
11296     
11297     getKeyEvent: function(){
11298         return this.useKeyDown ? 'keydown' : 'keypress';
11299     }
11300 };
11301
11302
11303 Ext.onReady = function(fn, scope, options) {
11304     Ext.Loader.onReady(fn, scope, true, options);
11305 };
11306
11307
11308 Ext.onDocumentReady = Ext.EventManager.onDocumentReady;
11309
11310
11311 Ext.EventManager.on = Ext.EventManager.addListener;
11312
11313
11314 Ext.EventManager.un = Ext.EventManager.removeListener;
11315
11316 (function(){
11317     var initExtCss = function() {
11318         
11319         var bd = document.body || document.getElementsByTagName('body')[0],
11320             baseCSSPrefix = Ext.baseCSSPrefix,
11321             cls = [baseCSSPrefix + 'body'],
11322             htmlCls = [],
11323             html;
11324
11325         if (!bd) {
11326             return false;
11327         }
11328
11329         html = bd.parentNode;
11330
11331         function add (c) {
11332             cls.push(baseCSSPrefix + c);
11333         }
11334
11335         
11336         if (Ext.isIE) {
11337             add('ie');
11338
11339             
11340             
11341             
11342             
11343             
11344             
11345             
11346             
11347             
11348             
11349             
11350             if (Ext.isIE6) {
11351                 add('ie6');
11352             } else { 
11353                 add('ie7p');
11354
11355                 if (Ext.isIE7) {
11356                     add('ie7');
11357                 } else {
11358                     add('ie8p');
11359
11360                     if (Ext.isIE8) {
11361                         add('ie8');
11362                     } else {
11363                         add('ie9p');
11364
11365                         if (Ext.isIE9) {
11366                             add('ie9');
11367                         }
11368                     }
11369                 }
11370             }
11371
11372             if (Ext.isIE6 || Ext.isIE7) {
11373                 add('ie7m');
11374             }
11375             if (Ext.isIE6 || Ext.isIE7 || Ext.isIE8) {
11376                 add('ie8m');
11377             }
11378             if (Ext.isIE7 || Ext.isIE8) {
11379                 add('ie78');
11380             }
11381         }
11382         if (Ext.isGecko) {
11383             add('gecko');
11384             if (Ext.isGecko3) {
11385                 add('gecko3');
11386             }
11387             if (Ext.isGecko4) {
11388                 add('gecko4');
11389             }
11390             if (Ext.isGecko5) {
11391                 add('gecko5');
11392             }
11393         }
11394         if (Ext.isOpera) {
11395             add('opera');
11396         }
11397         if (Ext.isWebKit) {
11398             add('webkit');
11399         }
11400         if (Ext.isSafari) {
11401             add('safari');
11402             if (Ext.isSafari2) {
11403                 add('safari2');
11404             }
11405             if (Ext.isSafari3) {
11406                 add('safari3');
11407             }
11408             if (Ext.isSafari4) {
11409                 add('safari4');
11410             }
11411             if (Ext.isSafari5) {
11412                 add('safari5');
11413             }
11414         }
11415         if (Ext.isChrome) {
11416             add('chrome');
11417         }
11418         if (Ext.isMac) {
11419             add('mac');
11420         }
11421         if (Ext.isLinux) {
11422             add('linux');
11423         }
11424         if (!Ext.supports.CSS3BorderRadius) {
11425             add('nbr');
11426         }
11427         if (!Ext.supports.CSS3LinearGradient) {
11428             add('nlg');
11429         }
11430         if (!Ext.scopeResetCSS) {
11431             add('reset');
11432         }
11433
11434         
11435         if (html) {
11436             if (Ext.isStrict && (Ext.isIE6 || Ext.isIE7)) {
11437                 Ext.isBorderBox = false;
11438             }
11439             else {
11440                 Ext.isBorderBox = true;
11441             }
11442
11443             htmlCls.push(baseCSSPrefix + (Ext.isBorderBox ? 'border-box' : 'strict'));
11444             if (!Ext.isStrict) {
11445                 htmlCls.push(baseCSSPrefix + 'quirks');
11446             }
11447             Ext.fly(html, '_internal').addCls(htmlCls);
11448         }
11449
11450         Ext.fly(bd, '_internal').addCls(cls);
11451         return true;
11452     };
11453
11454     Ext.onReady(initExtCss);
11455 })();
11456
11457
11458 Ext.define('Ext.EventObjectImpl', {
11459     uses: ['Ext.util.Point'],
11460
11461     
11462     BACKSPACE: 8,
11463     
11464     TAB: 9,
11465     
11466     NUM_CENTER: 12,
11467     
11468     ENTER: 13,
11469     
11470     RETURN: 13,
11471     
11472     SHIFT: 16,
11473     
11474     CTRL: 17,
11475     
11476     ALT: 18,
11477     
11478     PAUSE: 19,
11479     
11480     CAPS_LOCK: 20,
11481     
11482     ESC: 27,
11483     
11484     SPACE: 32,
11485     
11486     PAGE_UP: 33,
11487     
11488     PAGE_DOWN: 34,
11489     
11490     END: 35,
11491     
11492     HOME: 36,
11493     
11494     LEFT: 37,
11495     
11496     UP: 38,
11497     
11498     RIGHT: 39,
11499     
11500     DOWN: 40,
11501     
11502     PRINT_SCREEN: 44,
11503     
11504     INSERT: 45,
11505     
11506     DELETE: 46,
11507     
11508     ZERO: 48,
11509     
11510     ONE: 49,
11511     
11512     TWO: 50,
11513     
11514     THREE: 51,
11515     
11516     FOUR: 52,
11517     
11518     FIVE: 53,
11519     
11520     SIX: 54,
11521     
11522     SEVEN: 55,
11523     
11524     EIGHT: 56,
11525     
11526     NINE: 57,
11527     
11528     A: 65,
11529     
11530     B: 66,
11531     
11532     C: 67,
11533     
11534     D: 68,
11535     
11536     E: 69,
11537     
11538     F: 70,
11539     
11540     G: 71,
11541     
11542     H: 72,
11543     
11544     I: 73,
11545     
11546     J: 74,
11547     
11548     K: 75,
11549     
11550     L: 76,
11551     
11552     M: 77,
11553     
11554     N: 78,
11555     
11556     O: 79,
11557     
11558     P: 80,
11559     
11560     Q: 81,
11561     
11562     R: 82,
11563     
11564     S: 83,
11565     
11566     T: 84,
11567     
11568     U: 85,
11569     
11570     V: 86,
11571     
11572     W: 87,
11573     
11574     X: 88,
11575     
11576     Y: 89,
11577     
11578     Z: 90,
11579     
11580     CONTEXT_MENU: 93,
11581     
11582     NUM_ZERO: 96,
11583     
11584     NUM_ONE: 97,
11585     
11586     NUM_TWO: 98,
11587     
11588     NUM_THREE: 99,
11589     
11590     NUM_FOUR: 100,
11591     
11592     NUM_FIVE: 101,
11593     
11594     NUM_SIX: 102,
11595     
11596     NUM_SEVEN: 103,
11597     
11598     NUM_EIGHT: 104,
11599     
11600     NUM_NINE: 105,
11601     
11602     NUM_MULTIPLY: 106,
11603     
11604     NUM_PLUS: 107,
11605     
11606     NUM_MINUS: 109,
11607     
11608     NUM_PERIOD: 110,
11609     
11610     NUM_DIVISION: 111,
11611     
11612     F1: 112,
11613     
11614     F2: 113,
11615     
11616     F3: 114,
11617     
11618     F4: 115,
11619     
11620     F5: 116,
11621     
11622     F6: 117,
11623     
11624     F7: 118,
11625     
11626     F8: 119,
11627     
11628     F9: 120,
11629     
11630     F10: 121,
11631     
11632     F11: 122,
11633     
11634     F12: 123,
11635     
11636     WHEEL_SCALE: (function () {
11637         var scale;
11638
11639         if (Ext.isGecko) {
11640             
11641             scale = 3;
11642         } else if (Ext.isMac) {
11643             
11644             
11645             
11646
11647             if (Ext.isSafari && Ext.webKitVersion >= 532.0) {
11648                 
11649                 
11650                 
11651                 
11652                 
11653                 
11654                 scale = 120;
11655             } else {
11656                 
11657                 
11658                 scale = 12;
11659             }
11660
11661             
11662             
11663             
11664             
11665             scale *= 3;
11666         } else {
11667             
11668             scale = 120;
11669         }
11670
11671         return scale;
11672     })(),
11673
11674     
11675     clickRe: /(dbl)?click/,
11676     
11677     safariKeys: {
11678         3: 13, 
11679         63234: 37, 
11680         63235: 39, 
11681         63232: 38, 
11682         63233: 40, 
11683         63276: 33, 
11684         63277: 34, 
11685         63272: 46, 
11686         63273: 36, 
11687         63275: 35 
11688     },
11689     
11690     btnMap: Ext.isIE ? {
11691         1: 0,
11692         4: 1,
11693         2: 2
11694     } : {
11695         0: 0,
11696         1: 1,
11697         2: 2
11698     },
11699
11700     constructor: function(event, freezeEvent){
11701         if (event) {
11702             this.setEvent(event.browserEvent || event, freezeEvent);
11703         }
11704     },
11705
11706     setEvent: function(event, freezeEvent){
11707         var me = this, button, options;
11708
11709         if (event == me || (event && event.browserEvent)) { 
11710             return event;
11711         }
11712         me.browserEvent = event;
11713         if (event) {
11714             
11715             button = event.button ? me.btnMap[event.button] : (event.which ? event.which - 1 : -1);
11716             if (me.clickRe.test(event.type) && button == -1) {
11717                 button = 0;
11718             }
11719             options = {
11720                 type: event.type,
11721                 button: button,
11722                 shiftKey: event.shiftKey,
11723                 
11724                 ctrlKey: event.ctrlKey || event.metaKey || false,
11725                 altKey: event.altKey,
11726                 
11727                 keyCode: event.keyCode,
11728                 charCode: event.charCode,
11729                 
11730                 target: Ext.EventManager.getTarget(event),
11731                 relatedTarget: Ext.EventManager.getRelatedTarget(event),
11732                 currentTarget: event.currentTarget,
11733                 xy: (freezeEvent ? me.getXY() : null)
11734             };
11735         } else {
11736             options = {
11737                 button: -1,
11738                 shiftKey: false,
11739                 ctrlKey: false,
11740                 altKey: false,
11741                 keyCode: 0,
11742                 charCode: 0,
11743                 target: null,
11744                 xy: [0, 0]
11745             };
11746         }
11747         Ext.apply(me, options);
11748         return me;
11749     },
11750
11751     
11752     stopEvent: function(){
11753         this.stopPropagation();
11754         this.preventDefault();
11755     },
11756
11757     
11758     preventDefault: function(){
11759         if (this.browserEvent) {
11760             Ext.EventManager.preventDefault(this.browserEvent);
11761         }
11762     },
11763
11764     
11765     stopPropagation: function(){
11766         var browserEvent = this.browserEvent;
11767
11768         if (browserEvent) {
11769             if (browserEvent.type == 'mousedown') {
11770                 Ext.EventManager.stoppedMouseDownEvent.fire(this);
11771             }
11772             Ext.EventManager.stopPropagation(browserEvent);
11773         }
11774     },
11775
11776     
11777     getCharCode: function(){
11778         return this.charCode || this.keyCode;
11779     },
11780
11781     
11782     getKey: function(){
11783         return this.normalizeKey(this.keyCode || this.charCode);
11784     },
11785
11786     
11787     normalizeKey: function(key){
11788         
11789         return Ext.isWebKit ? (this.safariKeys[key] || key) : key;
11790     },
11791
11792     
11793     getPageX: function(){
11794         return this.getX();
11795     },
11796
11797     
11798     getPageY: function(){
11799         return this.getY();
11800     },
11801
11802     
11803     getX: function() {
11804         return this.getXY()[0];
11805     },
11806
11807     
11808     getY: function() {
11809         return this.getXY()[1];
11810     },
11811
11812     
11813     getXY: function() {
11814         if (!this.xy) {
11815             
11816             this.xy = Ext.EventManager.getPageXY(this.browserEvent);
11817         }
11818         return this.xy;
11819     },
11820
11821     
11822     getTarget : function(selector, maxDepth, returnEl){
11823         if (selector) {
11824             return Ext.fly(this.target).findParent(selector, maxDepth, returnEl);
11825         }
11826         return returnEl ? Ext.get(this.target) : this.target;
11827     },
11828
11829     
11830     getRelatedTarget : function(selector, maxDepth, returnEl){
11831         if (selector) {
11832             return Ext.fly(this.relatedTarget).findParent(selector, maxDepth, returnEl);
11833         }
11834         return returnEl ? Ext.get(this.relatedTarget) : this.relatedTarget;
11835     },
11836
11837     
11838     correctWheelDelta : function (delta) {
11839         var scale = this.WHEEL_SCALE,
11840             ret = Math.round(delta / scale);
11841
11842         if (!ret && delta) {
11843             ret = (delta < 0) ? -1 : 1; 
11844         }
11845
11846         return ret;
11847     },
11848
11849     
11850     getWheelDeltas : function () {
11851         var me = this,
11852             event = me.browserEvent,
11853             dx = 0, dy = 0; 
11854
11855         if (Ext.isDefined(event.wheelDeltaX)) { 
11856             dx = event.wheelDeltaX;
11857             dy = event.wheelDeltaY;
11858         } else if (event.wheelDelta) { 
11859             dy = event.wheelDelta;
11860         } else if (event.detail) { 
11861             dy = -event.detail; 
11862
11863             
11864             
11865             if (dy > 100) {
11866                 dy = 3;
11867             } else if (dy < -100) {
11868                 dy = -3;
11869             }
11870
11871             
11872             
11873             if (Ext.isDefined(event.axis) && event.axis === event.HORIZONTAL_AXIS) {
11874                 dx = dy;
11875                 dy = 0;
11876             }
11877         }
11878
11879         return {
11880             x: me.correctWheelDelta(dx),
11881             y: me.correctWheelDelta(dy)
11882         };
11883     },
11884
11885     
11886     getWheelDelta : function(){
11887         var deltas = this.getWheelDeltas();
11888
11889         return deltas.y;
11890     },
11891
11892     
11893     within : function(el, related, allowEl){
11894         if(el){
11895             var t = related ? this.getRelatedTarget() : this.getTarget(),
11896                 result;
11897
11898             if (t) {
11899                 result = Ext.fly(el).contains(t);
11900                 if (!result && allowEl) {
11901                     result = t == Ext.getDom(el);
11902                 }
11903                 return result;
11904             }
11905         }
11906         return false;
11907     },
11908
11909     
11910     isNavKeyPress : function(){
11911         var me = this,
11912             k = this.normalizeKey(me.keyCode);
11913
11914        return (k >= 33 && k <= 40) ||  
11915        k == me.RETURN ||
11916        k == me.TAB ||
11917        k == me.ESC;
11918     },
11919
11920     
11921     isSpecialKey : function(){
11922         var k = this.normalizeKey(this.keyCode);
11923         return (this.type == 'keypress' && this.ctrlKey) ||
11924         this.isNavKeyPress() ||
11925         (k == this.BACKSPACE) || 
11926         (k >= 16 && k <= 20) || 
11927         (k >= 44 && k <= 46);   
11928     },
11929
11930     
11931     getPoint : function(){
11932         var xy = this.getXY();
11933         return Ext.create('Ext.util.Point', xy[0], xy[1]);
11934     },
11935
11936    
11937     hasModifier : function(){
11938         return this.ctrlKey || this.altKey || this.shiftKey || this.metaKey;
11939     },
11940
11941     
11942     injectEvent: function () {
11943         var API,
11944             dispatchers = {}; 
11945
11946         
11947
11948         
11949         
11950
11951         if (!Ext.isIE && document.createEvent) { 
11952             API = {
11953                 createHtmlEvent: function (doc, type, bubbles, cancelable) {
11954                     var event = doc.createEvent('HTMLEvents');
11955
11956                     event.initEvent(type, bubbles, cancelable);
11957                     return event;
11958                 },
11959
11960                 createMouseEvent: function (doc, type, bubbles, cancelable, detail,
11961                                             clientX, clientY, ctrlKey, altKey, shiftKey, metaKey,
11962                                             button, relatedTarget) {
11963                     var event = doc.createEvent('MouseEvents'),
11964                         view = doc.defaultView || window;
11965
11966                     if (event.initMouseEvent) {
11967                         event.initMouseEvent(type, bubbles, cancelable, view, detail,
11968                                     clientX, clientY, clientX, clientY, ctrlKey, altKey,
11969                                     shiftKey, metaKey, button, relatedTarget);
11970                     } else { 
11971                         event = doc.createEvent('UIEvents');
11972                         event.initEvent(type, bubbles, cancelable);
11973                         event.view = view;
11974                         event.detail = detail;
11975                         event.screenX = clientX;
11976                         event.screenY = clientY;
11977                         event.clientX = clientX;
11978                         event.clientY = clientY;
11979                         event.ctrlKey = ctrlKey;
11980                         event.altKey = altKey;
11981                         event.metaKey = metaKey;
11982                         event.shiftKey = shiftKey;
11983                         event.button = button;
11984                         event.relatedTarget = relatedTarget;
11985                     }
11986
11987                     return event;
11988                 },
11989
11990                 createUIEvent: function (doc, type, bubbles, cancelable, detail) {
11991                     var event = doc.createEvent('UIEvents'),
11992                         view = doc.defaultView || window;
11993
11994                     event.initUIEvent(type, bubbles, cancelable, view, detail);
11995                     return event;
11996                 },
11997
11998                 fireEvent: function (target, type, event) {
11999                     target.dispatchEvent(event);
12000                 },
12001
12002                 fixTarget: function (target) {
12003                     
12004                     if (target == window && !target.dispatchEvent) {
12005                         return document;
12006                     }
12007
12008                     return target;
12009                 }
12010             };
12011         } else if (document.createEventObject) { 
12012             var crazyIEButtons = { 0: 1, 1: 4, 2: 2 };
12013
12014             API = {
12015                 createHtmlEvent: function (doc, type, bubbles, cancelable) {
12016                     var event = doc.createEventObject();
12017                     event.bubbles = bubbles;
12018                     event.cancelable = cancelable;
12019                     return event;
12020                 },
12021
12022                 createMouseEvent: function (doc, type, bubbles, cancelable, detail,
12023                                             clientX, clientY, ctrlKey, altKey, shiftKey, metaKey,
12024                                             button, relatedTarget) {
12025                     var event = doc.createEventObject();
12026                     event.bubbles = bubbles;
12027                     event.cancelable = cancelable;
12028                     event.detail = detail;
12029                     event.screenX = clientX;
12030                     event.screenY = clientY;
12031                     event.clientX = clientX;
12032                     event.clientY = clientY;
12033                     event.ctrlKey = ctrlKey;
12034                     event.altKey = altKey;
12035                     event.shiftKey = shiftKey;
12036                     event.metaKey = metaKey;
12037                     event.button = crazyIEButtons[button] || button;
12038                     event.relatedTarget = relatedTarget; 
12039                     return event;
12040                 },
12041
12042                 createUIEvent: function (doc, type, bubbles, cancelable, detail) {
12043                     var event = doc.createEventObject();
12044                     event.bubbles = bubbles;
12045                     event.cancelable = cancelable;
12046                     return event;
12047                 },
12048
12049                 fireEvent: function (target, type, event) {
12050                     target.fireEvent('on' + type, event);
12051                 },
12052
12053                 fixTarget: function (target) {
12054                     if (target == document) {
12055                         
12056                         
12057                         return document.documentElement;
12058                     }
12059
12060                     return target;
12061                 }
12062             };
12063         }
12064
12065         
12066         
12067
12068         Ext.Object.each({
12069                 load:   [false, false],
12070                 unload: [false, false],
12071                 select: [true, false],
12072                 change: [true, false],
12073                 submit: [true, true],
12074                 reset:  [true, false],
12075                 resize: [true, false],
12076                 scroll: [true, false]
12077             },
12078             function (name, value) {
12079                 var bubbles = value[0], cancelable = value[1];
12080                 dispatchers[name] = function (targetEl, srcEvent) {
12081                     var e = API.createHtmlEvent(name, bubbles, cancelable);
12082                     API.fireEvent(targetEl, name, e);
12083                 };
12084             });
12085
12086         
12087         
12088
12089         function createMouseEventDispatcher (type, detail) {
12090             var cancelable = (type != 'mousemove');
12091             return function (targetEl, srcEvent) {
12092                 var xy = srcEvent.getXY(),
12093                     e = API.createMouseEvent(targetEl.ownerDocument, type, true, cancelable,
12094                                 detail, xy[0], xy[1], srcEvent.ctrlKey, srcEvent.altKey,
12095                                 srcEvent.shiftKey, srcEvent.metaKey, srcEvent.button,
12096                                 srcEvent.relatedTarget);
12097                 API.fireEvent(targetEl, type, e);
12098             };
12099         }
12100
12101         Ext.each(['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mousemove', 'mouseout'],
12102             function (eventName) {
12103                 dispatchers[eventName] = createMouseEventDispatcher(eventName, 1);
12104             });
12105
12106         
12107         
12108
12109         Ext.Object.each({
12110                 focusin:  [true, false],
12111                 focusout: [true, false],
12112                 activate: [true, true],
12113                 focus:    [false, false],
12114                 blur:     [false, false]
12115             },
12116             function (name, value) {
12117                 var bubbles = value[0], cancelable = value[1];
12118                 dispatchers[name] = function (targetEl, srcEvent) {
12119                     var e = API.createUIEvent(targetEl.ownerDocument, name, bubbles, cancelable, 1);
12120                     API.fireEvent(targetEl, name, e);
12121                 };
12122             });
12123
12124         
12125         if (!API) {
12126             
12127
12128             dispatchers = {}; 
12129
12130             API = {
12131                 fixTarget: function (t) {
12132                     return t;
12133                 }
12134             };
12135         }
12136
12137         function cannotInject (target, srcEvent) {
12138         }
12139
12140         return function (target) {
12141             var me = this,
12142                 dispatcher = dispatchers[me.type] || cannotInject,
12143                 t = target ? (target.dom || target) : me.getTarget();
12144
12145             t = API.fixTarget(t);
12146             dispatcher(t, me);
12147         };
12148     }() 
12149
12150 }, function() {
12151
12152 Ext.EventObject = new Ext.EventObjectImpl();
12153
12154 });
12155
12156
12157
12158 (function(){
12159     var doc = document,
12160         activeElement = null,
12161         isCSS1 = doc.compatMode == "CSS1Compat",
12162         ELEMENT = Ext.Element,
12163         fly = function(el){
12164             if (!_fly) {
12165                 _fly = new Ext.Element.Flyweight();
12166             }
12167             _fly.dom = el;
12168             return _fly;
12169         }, _fly;
12170
12171     
12172     
12173     
12174     if (!('activeElement' in doc) && doc.addEventListener) {
12175         doc.addEventListener('focus',
12176             function (ev) {
12177                 if (ev && ev.target) {
12178                     activeElement = (ev.target == doc) ? null : ev.target;
12179                 }
12180             }, true);
12181     }
12182
12183     
12184     function makeSelectionRestoreFn (activeEl, start, end) {
12185         return function () {
12186             activeEl.selectionStart = start;
12187             activeEl.selectionEnd = end;
12188         };
12189     }
12190
12191     Ext.apply(ELEMENT, {
12192         isAncestor : function(p, c) {
12193             var ret = false;
12194
12195             p = Ext.getDom(p);
12196             c = Ext.getDom(c);
12197             if (p && c) {
12198                 if (p.contains) {
12199                     return p.contains(c);
12200                 } else if (p.compareDocumentPosition) {
12201                     return !!(p.compareDocumentPosition(c) & 16);
12202                 } else {
12203                     while ((c = c.parentNode)) {
12204                         ret = c == p || ret;
12205                     }
12206                 }
12207             }
12208             return ret;
12209         },
12210
12211         
12212         getActiveElement: function () {
12213             return doc.activeElement || activeElement;
12214         },
12215
12216         
12217         getRightMarginFixCleaner: function (target) {
12218             var supports = Ext.supports,
12219                 hasInputBug = supports.DisplayChangeInputSelectionBug,
12220                 hasTextAreaBug = supports.DisplayChangeTextAreaSelectionBug;
12221
12222             if (hasInputBug || hasTextAreaBug) {
12223                 var activeEl = doc.activeElement || activeElement, 
12224                     tag = activeEl && activeEl.tagName,
12225                     start,
12226                     end;
12227
12228                 if ((hasTextAreaBug && tag == 'TEXTAREA') ||
12229                     (hasInputBug && tag == 'INPUT' && activeEl.type == 'text')) {
12230                     if (ELEMENT.isAncestor(target, activeEl)) {
12231                         start = activeEl.selectionStart;
12232                         end = activeEl.selectionEnd;
12233
12234                         if (Ext.isNumber(start) && Ext.isNumber(end)) { 
12235                             
12236                             
12237                             
12238                             
12239                             return makeSelectionRestoreFn(activeEl, start, end);
12240                         }
12241                     }
12242                 }
12243             }
12244
12245             return Ext.emptyFn; 
12246         },
12247
12248         getViewWidth : function(full) {
12249             return full ? ELEMENT.getDocumentWidth() : ELEMENT.getViewportWidth();
12250         },
12251
12252         getViewHeight : function(full) {
12253             return full ? ELEMENT.getDocumentHeight() : ELEMENT.getViewportHeight();
12254         },
12255
12256         getDocumentHeight: function() {
12257             return Math.max(!isCSS1 ? doc.body.scrollHeight : doc.documentElement.scrollHeight, ELEMENT.getViewportHeight());
12258         },
12259
12260         getDocumentWidth: function() {
12261             return Math.max(!isCSS1 ? doc.body.scrollWidth : doc.documentElement.scrollWidth, ELEMENT.getViewportWidth());
12262         },
12263
12264         getViewportHeight: function(){
12265             return Ext.isIE ?
12266                    (Ext.isStrict ? doc.documentElement.clientHeight : doc.body.clientHeight) :
12267                    self.innerHeight;
12268         },
12269
12270         getViewportWidth : function() {
12271             return (!Ext.isStrict && !Ext.isOpera) ? doc.body.clientWidth :
12272                    Ext.isIE ? doc.documentElement.clientWidth : self.innerWidth;
12273         },
12274
12275         getY : function(el) {
12276             return ELEMENT.getXY(el)[1];
12277         },
12278
12279         getX : function(el) {
12280             return ELEMENT.getXY(el)[0];
12281         },
12282
12283         getOffsetParent: function (el) {
12284             el = Ext.getDom(el);
12285             try {
12286                 
12287                 return el.offsetParent;
12288             } catch (e) {
12289                 var body = document.body; 
12290                 return (el == body) ? null : body;
12291             }
12292         },
12293
12294         getXY : function(el) {
12295             var p,
12296                 pe,
12297                 b,
12298                 bt,
12299                 bl,
12300                 dbd,
12301                 x = 0,
12302                 y = 0,
12303                 scroll,
12304                 hasAbsolute,
12305                 bd = (doc.body || doc.documentElement),
12306                 ret;
12307
12308             el = Ext.getDom(el);
12309
12310             if(el != bd){
12311                 hasAbsolute = fly(el).isStyle("position", "absolute");
12312
12313                 if (el.getBoundingClientRect) {
12314                     try {
12315                         b = el.getBoundingClientRect();
12316                         scroll = fly(document).getScroll();
12317                         ret = [ Math.round(b.left + scroll.left), Math.round(b.top + scroll.top) ];
12318                     } catch (e) {
12319                         
12320                     }
12321                 }
12322
12323                 if (!ret) {
12324                     for (p = el; p; p = ELEMENT.getOffsetParent(p)) {
12325                         pe = fly(p);
12326                         x += p.offsetLeft;
12327                         y += p.offsetTop;
12328
12329                         hasAbsolute = hasAbsolute || pe.isStyle("position", "absolute");
12330
12331                         if (Ext.isGecko) {
12332                             y += bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
12333                             x += bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
12334
12335                             if (p != el && !pe.isStyle('overflow','visible')) {
12336                                 x += bl;
12337                                 y += bt;
12338                             }
12339                         }
12340                     }
12341
12342                     if (Ext.isSafari && hasAbsolute) {
12343                         x -= bd.offsetLeft;
12344                         y -= bd.offsetTop;
12345                     }
12346
12347                     if (Ext.isGecko && !hasAbsolute) {
12348                         dbd = fly(bd);
12349                         x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
12350                         y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
12351                     }
12352
12353                     p = el.parentNode;
12354                     while (p && p != bd) {
12355                         if (!Ext.isOpera || (p.tagName != 'TR' && !fly(p).isStyle("display", "inline"))) {
12356                             x -= p.scrollLeft;
12357                             y -= p.scrollTop;
12358                         }
12359                         p = p.parentNode;
12360                     }
12361                     ret = [x,y];
12362                 }
12363             }
12364             return ret || [0,0];
12365         },
12366
12367         setXY : function(el, xy) {
12368             (el = Ext.fly(el, '_setXY')).position();
12369
12370             var pts = el.translatePoints(xy),
12371                 style = el.dom.style,
12372                 pos;
12373
12374             for (pos in pts) {
12375                 if (!isNaN(pts[pos])) {
12376                     style[pos] = pts[pos] + "px";
12377                 }
12378             }
12379         },
12380
12381         setX : function(el, x) {
12382             ELEMENT.setXY(el, [x, false]);
12383         },
12384
12385         setY : function(el, y) {
12386             ELEMENT.setXY(el, [false, y]);
12387         },
12388
12389         
12390         serializeForm: function(form) {
12391             var fElements = form.elements || (document.forms[form] || Ext.getDom(form)).elements,
12392                 hasSubmit = false,
12393                 encoder = encodeURIComponent,
12394                 name,
12395                 data = '',
12396                 type,
12397                 hasValue;
12398
12399             Ext.each(fElements, function(element){
12400                 name = element.name;
12401                 type = element.type;
12402
12403                 if (!element.disabled && name) {
12404                     if (/select-(one|multiple)/i.test(type)) {
12405                         Ext.each(element.options, function(opt){
12406                             if (opt.selected) {
12407                                 hasValue = opt.hasAttribute ? opt.hasAttribute('value') : opt.getAttributeNode('value').specified;
12408                                 data += Ext.String.format("{0}={1}&", encoder(name), encoder(hasValue ? opt.value : opt.text));
12409                             }
12410                         });
12411                     } else if (!(/file|undefined|reset|button/i.test(type))) {
12412                         if (!(/radio|checkbox/i.test(type) && !element.checked) && !(type == 'submit' && hasSubmit)) {
12413                             data += encoder(name) + '=' + encoder(element.value) + '&';
12414                             hasSubmit = /submit/i.test(type);
12415                         }
12416                     }
12417                 }
12418             });
12419             return data.substr(0, data.length - 1);
12420         }
12421     });
12422 })();
12423
12424
12425
12426 Ext.Element.addMethods((function(){
12427     var focusRe = /button|input|textarea|select|object/;
12428     return {
12429         
12430         monitorMouseLeave: function(delay, handler, scope) {
12431             var me = this,
12432                 timer,
12433                 listeners = {
12434                     mouseleave: function(e) {
12435                         timer = setTimeout(Ext.Function.bind(handler, scope||me, [e]), delay);
12436                     },
12437                     mouseenter: function() {
12438                         clearTimeout(timer);
12439                     },
12440                     freezeEvent: true
12441                 };
12442
12443             me.on(listeners);
12444             return listeners;
12445         },
12446
12447         
12448         swallowEvent : function(eventName, preventDefault) {
12449             var me = this;
12450             function fn(e) {
12451                 e.stopPropagation();
12452                 if (preventDefault) {
12453                     e.preventDefault();
12454                 }
12455             }
12456
12457             if (Ext.isArray(eventName)) {
12458                 Ext.each(eventName, function(e) {
12459                      me.on(e, fn);
12460                 });
12461                 return me;
12462             }
12463             me.on(eventName, fn);
12464             return me;
12465         },
12466
12467         
12468         relayEvent : function(eventName, observable) {
12469             this.on(eventName, function(e) {
12470                 observable.fireEvent(eventName, e);
12471             });
12472         },
12473
12474         
12475         clean : function(forceReclean) {
12476             var me  = this,
12477                 dom = me.dom,
12478                 n   = dom.firstChild,
12479                 nx,
12480                 ni  = -1;
12481     
12482             if (Ext.Element.data(dom, 'isCleaned') && forceReclean !== true) {
12483                 return me;
12484             }
12485
12486             while (n) {
12487                 nx = n.nextSibling;
12488                 if (n.nodeType == 3) {
12489                     
12490                     if (!(/\S/.test(n.nodeValue))) {
12491                         dom.removeChild(n);
12492                     
12493                     } else if (nx && nx.nodeType == 3) {
12494                         n.appendData(Ext.String.trim(nx.data));
12495                         dom.removeChild(nx);
12496                         nx = n.nextSibling;
12497                         n.nodeIndex = ++ni;
12498                     }
12499                 } else {
12500                     
12501                     Ext.fly(n).clean();
12502                     n.nodeIndex = ++ni;
12503                 }
12504                 n = nx;
12505             }
12506
12507             Ext.Element.data(dom, 'isCleaned', true);
12508             return me;
12509         },
12510
12511         
12512         load : function(options) {
12513             this.getLoader().load(options);
12514             return this;
12515         },
12516
12517         
12518         getLoader : function() {
12519             var dom = this.dom,
12520                 data = Ext.Element.data,
12521                 loader = data(dom, 'loader');
12522     
12523             if (!loader) {
12524                 loader = Ext.create('Ext.ElementLoader', {
12525                     target: this
12526                 });
12527                 data(dom, 'loader', loader);
12528             }
12529             return loader;
12530         },
12531
12532         
12533         update : function(html, loadScripts, callback) {
12534             var me = this,
12535                 id,
12536                 dom,
12537                 interval;
12538
12539             if (!me.dom) {
12540                 return me;
12541             }
12542             html = html || '';
12543             dom = me.dom;
12544
12545             if (loadScripts !== true) {
12546                 dom.innerHTML = html;
12547                 Ext.callback(callback, me);
12548                 return me;
12549             }
12550
12551             id  = Ext.id();
12552             html += '<span id="' + id + '"></span>';
12553
12554             interval = setInterval(function(){
12555                 if (!document.getElementById(id)) {
12556                     return false;
12557                 }
12558                 clearInterval(interval);
12559                 var DOC    = document,
12560                     hd     = DOC.getElementsByTagName("head")[0],
12561                     re     = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,
12562                     srcRe  = /\ssrc=([\'\"])(.*?)\1/i,
12563                     typeRe = /\stype=([\'\"])(.*?)\1/i,
12564                     match,
12565                     attrs,
12566                     srcMatch,
12567                     typeMatch,
12568                     el,
12569                     s;
12570
12571                 while ((match = re.exec(html))) {
12572                     attrs = match[1];
12573                     srcMatch = attrs ? attrs.match(srcRe) : false;
12574                     if (srcMatch && srcMatch[2]) {
12575                        s = DOC.createElement("script");
12576                        s.src = srcMatch[2];
12577                        typeMatch = attrs.match(typeRe);
12578                        if (typeMatch && typeMatch[2]) {
12579                            s.type = typeMatch[2];
12580                        }
12581                        hd.appendChild(s);
12582                     } else if (match[2] && match[2].length > 0) {
12583                         if (window.execScript) {
12584                            window.execScript(match[2]);
12585                         } else {
12586                            window.eval(match[2]);
12587                         }
12588                     }
12589                 }
12590
12591                 el = DOC.getElementById(id);
12592                 if (el) {
12593                     Ext.removeNode(el);
12594                 }
12595                 Ext.callback(callback, me);
12596             }, 20);
12597             dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, '');
12598             return me;
12599         },
12600
12601         
12602         removeAllListeners : function() {
12603             this.removeAnchor();
12604             Ext.EventManager.removeAll(this.dom);
12605             return this;
12606         },
12607     
12608         
12609         getScopeParent: function(){
12610             var parent = this.dom.parentNode;
12611             return Ext.scopeResetCSS ? parent.parentNode : parent;
12612         },
12613
12614         
12615         createProxy : function(config, renderTo, matchBox) {
12616             config = (typeof config == 'object') ? config : {tag : "div", cls: config};
12617
12618             var me = this,
12619                 proxy = renderTo ? Ext.DomHelper.append(renderTo, config, true) :
12620                                    Ext.DomHelper.insertBefore(me.dom, config, true);
12621
12622             proxy.setVisibilityMode(Ext.Element.DISPLAY);
12623             proxy.hide();
12624             if (matchBox && me.setBox && me.getBox) { 
12625                proxy.setBox(me.getBox());
12626             }
12627             return proxy;
12628         },
12629     
12630         
12631         focusable: function(){
12632             var dom = this.dom,
12633                 nodeName = dom.nodeName.toLowerCase(),
12634                 canFocus = false,
12635                 hasTabIndex = !isNaN(dom.tabIndex);
12636             
12637             if (!dom.disabled) {
12638                 if (focusRe.test(nodeName)) {
12639                     canFocus = true;
12640                 } else {
12641                     canFocus = nodeName == 'a' ? dom.href || hasTabIndex : hasTabIndex;
12642                 }
12643             }
12644             return canFocus && this.isVisible(true);
12645         }    
12646     };
12647 })());
12648 Ext.Element.prototype.clearListeners = Ext.Element.prototype.removeAllListeners;
12649
12650
12651 Ext.Element.addMethods({
12652     
12653     getAnchorXY : function(anchor, local, s){
12654         
12655         
12656         anchor = (anchor || "tl").toLowerCase();
12657         s = s || {};
12658
12659         var me = this,
12660             vp = me.dom == document.body || me.dom == document,
12661             w = s.width || vp ? Ext.Element.getViewWidth() : me.getWidth(),
12662             h = s.height || vp ? Ext.Element.getViewHeight() : me.getHeight(),
12663             xy,
12664             r = Math.round,
12665             o = me.getXY(),
12666             scroll = me.getScroll(),
12667             extraX = vp ? scroll.left : !local ? o[0] : 0,
12668             extraY = vp ? scroll.top : !local ? o[1] : 0,
12669             hash = {
12670                 c  : [r(w * 0.5), r(h * 0.5)],
12671                 t  : [r(w * 0.5), 0],
12672                 l  : [0, r(h * 0.5)],
12673                 r  : [w, r(h * 0.5)],
12674                 b  : [r(w * 0.5), h],
12675                 tl : [0, 0],
12676                 bl : [0, h],
12677                 br : [w, h],
12678                 tr : [w, 0]
12679             };
12680
12681         xy = hash[anchor];
12682         return [xy[0] + extraX, xy[1] + extraY];
12683     },
12684
12685     
12686     anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
12687         var me = this,
12688             dom = me.dom,
12689             scroll = !Ext.isEmpty(monitorScroll),
12690             action = function(){
12691                 Ext.fly(dom).alignTo(el, alignment, offsets, animate);
12692                 Ext.callback(callback, Ext.fly(dom));
12693             },
12694             anchor = this.getAnchor();
12695
12696         
12697         this.removeAnchor();
12698         Ext.apply(anchor, {
12699             fn: action,
12700             scroll: scroll
12701         });
12702
12703         Ext.EventManager.onWindowResize(action, null);
12704
12705         if(scroll){
12706             Ext.EventManager.on(window, 'scroll', action, null,
12707                 {buffer: !isNaN(monitorScroll) ? monitorScroll : 50});
12708         }
12709         action.call(me); 
12710         return me;
12711     },
12712
12713     
12714     removeAnchor : function(){
12715         var me = this,
12716             anchor = this.getAnchor();
12717
12718         if(anchor && anchor.fn){
12719             Ext.EventManager.removeResizeListener(anchor.fn);
12720             if(anchor.scroll){
12721                 Ext.EventManager.un(window, 'scroll', anchor.fn);
12722             }
12723             delete anchor.fn;
12724         }
12725         return me;
12726     },
12727
12728     
12729     getAnchor : function(){
12730         var data = Ext.Element.data,
12731             dom = this.dom;
12732             if (!dom) {
12733                 return;
12734             }
12735             var anchor = data(dom, '_anchor');
12736
12737         if(!anchor){
12738             anchor = data(dom, '_anchor', {});
12739         }
12740         return anchor;
12741     },
12742
12743     getAlignVector: function(el, spec, offset) {
12744         var me = this,
12745             side = {t:"top", l:"left", r:"right", b: "bottom"},
12746             thisRegion = me.getRegion(),
12747             elRegion;
12748
12749         el = Ext.get(el);
12750         if(!el || !el.dom){
12751         }
12752
12753         elRegion = el.getRegion();
12754     },
12755
12756     
12757     getAlignToXY : function(el, p, o){
12758         el = Ext.get(el);
12759
12760         if(!el || !el.dom){
12761         }
12762
12763         o = o || [0,0];
12764         p = (!p || p == "?" ? "tl-bl?" : (!(/-/).test(p) && p !== "" ? "tl-" + p : p || "tl-bl")).toLowerCase();
12765
12766         var me = this,
12767             d = me.dom,
12768             a1,
12769             a2,
12770             x,
12771             y,
12772             
12773             w,
12774             h,
12775             r,
12776             dw = Ext.Element.getViewWidth() -10, 
12777             dh = Ext.Element.getViewHeight()-10, 
12778             p1y,
12779             p1x,
12780             p2y,
12781             p2x,
12782             swapY,
12783             swapX,
12784             doc = document,
12785             docElement = doc.documentElement,
12786             docBody = doc.body,
12787             scrollX = (docElement.scrollLeft || docBody.scrollLeft || 0)+5,
12788             scrollY = (docElement.scrollTop || docBody.scrollTop || 0)+5,
12789             c = false, 
12790             p1 = "",
12791             p2 = "",
12792             m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
12793
12794         if(!m){
12795         }
12796
12797         p1 = m[1];
12798         p2 = m[2];
12799         c = !!m[3];
12800
12801         
12802         
12803         a1 = me.getAnchorXY(p1, true);
12804         a2 = el.getAnchorXY(p2, false);
12805
12806         x = a2[0] - a1[0] + o[0];
12807         y = a2[1] - a1[1] + o[1];
12808
12809         if(c){
12810            w = me.getWidth();
12811            h = me.getHeight();
12812            r = el.getRegion();
12813            
12814            
12815            
12816            p1y = p1.charAt(0);
12817            p1x = p1.charAt(p1.length-1);
12818            p2y = p2.charAt(0);
12819            p2x = p2.charAt(p2.length-1);
12820            swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
12821            swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
12822
12823
12824            if (x + w > dw + scrollX) {
12825                 x = swapX ? r.left-w : dw+scrollX-w;
12826            }
12827            if (x < scrollX) {
12828                x = swapX ? r.right : scrollX;
12829            }
12830            if (y + h > dh + scrollY) {
12831                 y = swapY ? r.top-h : dh+scrollY-h;
12832             }
12833            if (y < scrollY){
12834                y = swapY ? r.bottom : scrollY;
12835            }
12836         }
12837         return [x,y];
12838     },
12839
12840     
12841     alignTo : function(element, position, offsets, animate){
12842         var me = this;
12843         return me.setXY(me.getAlignToXY(element, position, offsets),
12844                         me.anim && !!animate ? me.anim(animate) : false);
12845     },
12846
12847     
12848     adjustForConstraints : function(xy, parent) {
12849         var vector = this.getConstrainVector(parent, xy);
12850         if (vector) {
12851             xy[0] += vector[0];
12852             xy[1] += vector[1];
12853         }
12854         return xy;
12855     },
12856
12857     
12858     getConstrainVector: function(constrainTo, proposedPosition) {
12859         if (!(constrainTo instanceof Ext.util.Region)) {
12860             constrainTo = Ext.get(constrainTo).getViewRegion();
12861         }
12862         var thisRegion = this.getRegion(),
12863             vector = [0, 0],
12864             shadowSize = this.shadow && this.shadow.offset,
12865             overflowed = false;
12866
12867         
12868         if (proposedPosition) {
12869             thisRegion.translateBy(proposedPosition[0] - thisRegion.x, proposedPosition[1] - thisRegion.y);
12870         }
12871
12872         
12873         
12874         if (shadowSize) {
12875             constrainTo.adjust(0, -shadowSize, -shadowSize, shadowSize);
12876         }
12877
12878         
12879         if (thisRegion.right > constrainTo.right) {
12880             overflowed = true;
12881             vector[0] = (constrainTo.right - thisRegion.right);    
12882         }
12883         if (thisRegion.left + vector[0] < constrainTo.left) {
12884             overflowed = true;
12885             vector[0] = (constrainTo.left - thisRegion.left);      
12886         }
12887
12888         
12889         if (thisRegion.bottom > constrainTo.bottom) {
12890             overflowed = true;
12891             vector[1] = (constrainTo.bottom - thisRegion.bottom);  
12892         }
12893         if (thisRegion.top + vector[1] < constrainTo.top) {
12894             overflowed = true;
12895             vector[1] = (constrainTo.top - thisRegion.top);        
12896         }
12897         return overflowed ? vector : false;
12898     },
12899
12900     
12901     getCenterXY : function(){
12902         return this.getAlignToXY(document, 'c-c');
12903     },
12904
12905     
12906     center : function(centerIn){
12907         return this.alignTo(centerIn || document, 'c-c');
12908     }
12909 });
12910
12911
12912 (function(){
12913
12914 var ELEMENT = Ext.Element,
12915     LEFT = "left",
12916     RIGHT = "right",
12917     TOP = "top",
12918     BOTTOM = "bottom",
12919     POSITION = "position",
12920     STATIC = "static",
12921     RELATIVE = "relative",
12922     AUTO = "auto",
12923     ZINDEX = "z-index";
12924
12925 Ext.override(Ext.Element, {
12926     
12927     getX : function(){
12928         return ELEMENT.getX(this.dom);
12929     },
12930
12931     
12932     getY : function(){
12933         return ELEMENT.getY(this.dom);
12934     },
12935
12936     
12937     getXY : function(){
12938         return ELEMENT.getXY(this.dom);
12939     },
12940
12941     
12942     getOffsetsTo : function(el){
12943         var o = this.getXY(),
12944             e = Ext.fly(el, '_internal').getXY();
12945         return [o[0]-e[0],o[1]-e[1]];
12946     },
12947
12948     
12949     setX : function(x, animate){
12950         return this.setXY([x, this.getY()], animate);
12951     },
12952
12953     
12954     setY : function(y, animate){
12955         return this.setXY([this.getX(), y], animate);
12956     },
12957
12958     
12959     setLeft : function(left){
12960         this.setStyle(LEFT, this.addUnits(left));
12961         return this;
12962     },
12963
12964     
12965     setTop : function(top){
12966         this.setStyle(TOP, this.addUnits(top));
12967         return this;
12968     },
12969
12970     
12971     setRight : function(right){
12972         this.setStyle(RIGHT, this.addUnits(right));
12973         return this;
12974     },
12975
12976     
12977     setBottom : function(bottom){
12978         this.setStyle(BOTTOM, this.addUnits(bottom));
12979         return this;
12980     },
12981
12982     
12983     setXY: function(pos, animate) {
12984         var me = this;
12985         if (!animate || !me.anim) {
12986             ELEMENT.setXY(me.dom, pos);
12987         }
12988         else {
12989             if (!Ext.isObject(animate)) {
12990                 animate = {};
12991             }
12992             me.animate(Ext.applyIf({ to: { x: pos[0], y: pos[1] } }, animate));
12993         }
12994         return me;
12995     },
12996
12997     
12998     setLocation : function(x, y, animate){
12999         return this.setXY([x, y], animate);
13000     },
13001
13002     
13003     moveTo : function(x, y, animate){
13004         return this.setXY([x, y], animate);
13005     },
13006
13007     
13008     getLeft : function(local){
13009         return !local ? this.getX() : parseInt(this.getStyle(LEFT), 10) || 0;
13010     },
13011
13012     
13013     getRight : function(local){
13014         var me = this;
13015         return !local ? me.getX() + me.getWidth() : (me.getLeft(true) + me.getWidth()) || 0;
13016     },
13017
13018     
13019     getTop : function(local) {
13020         return !local ? this.getY() : parseInt(this.getStyle(TOP), 10) || 0;
13021     },
13022
13023     
13024     getBottom : function(local){
13025         var me = this;
13026         return !local ? me.getY() + me.getHeight() : (me.getTop(true) + me.getHeight()) || 0;
13027     },
13028
13029     
13030     position : function(pos, zIndex, x, y) {
13031         var me = this;
13032
13033         if (!pos && me.isStyle(POSITION, STATIC)){
13034             me.setStyle(POSITION, RELATIVE);
13035         } else if(pos) {
13036             me.setStyle(POSITION, pos);
13037         }
13038         if (zIndex){
13039             me.setStyle(ZINDEX, zIndex);
13040         }
13041         if (x || y) {
13042             me.setXY([x || false, y || false]);
13043         }
13044     },
13045
13046     
13047     clearPositioning : function(value){
13048         value = value || '';
13049         this.setStyle({
13050             left : value,
13051             right : value,
13052             top : value,
13053             bottom : value,
13054             "z-index" : "",
13055             position : STATIC
13056         });
13057         return this;
13058     },
13059
13060     
13061     getPositioning : function(){
13062         var l = this.getStyle(LEFT);
13063         var t = this.getStyle(TOP);
13064         return {
13065             "position" : this.getStyle(POSITION),
13066             "left" : l,
13067             "right" : l ? "" : this.getStyle(RIGHT),
13068             "top" : t,
13069             "bottom" : t ? "" : this.getStyle(BOTTOM),
13070             "z-index" : this.getStyle(ZINDEX)
13071         };
13072     },
13073
13074     
13075     setPositioning : function(pc){
13076         var me = this,
13077             style = me.dom.style;
13078
13079         me.setStyle(pc);
13080
13081         if(pc.right == AUTO){
13082             style.right = "";
13083         }
13084         if(pc.bottom == AUTO){
13085             style.bottom = "";
13086         }
13087
13088         return me;
13089     },
13090
13091     
13092     translatePoints: function(x, y) {
13093         if (Ext.isArray(x)) {
13094              y = x[1];
13095              x = x[0];
13096         }
13097         var me = this,
13098             relative = me.isStyle(POSITION, RELATIVE),
13099             o = me.getXY(),
13100             left = parseInt(me.getStyle(LEFT), 10),
13101             top = parseInt(me.getStyle(TOP), 10);
13102
13103         if (!Ext.isNumber(left)) {
13104             left = relative ? 0 : me.dom.offsetLeft;
13105         }
13106         if (!Ext.isNumber(top)) {
13107             top = relative ? 0 : me.dom.offsetTop;
13108         }
13109         left = (Ext.isNumber(x)) ? x - o[0] + left : undefined;
13110         top = (Ext.isNumber(y)) ? y - o[1] + top : undefined;
13111         return {
13112             left: left,
13113             top: top
13114         };
13115     },
13116
13117     
13118     setBox: function(box, adjust, animate) {
13119         var me = this,
13120             w = box.width,
13121             h = box.height;
13122         if ((adjust && !me.autoBoxAdjust) && !me.isBorderBox()) {
13123             w -= (me.getBorderWidth("lr") + me.getPadding("lr"));
13124             h -= (me.getBorderWidth("tb") + me.getPadding("tb"));
13125         }
13126         me.setBounds(box.x, box.y, w, h, animate);
13127         return me;
13128     },
13129
13130     
13131     getBox: function(contentBox, local) {
13132         var me = this,
13133             xy,
13134             left,
13135             top,
13136             getBorderWidth = me.getBorderWidth,
13137             getPadding = me.getPadding,
13138             l, r, t, b, w, h, bx;
13139         if (!local) {
13140             xy = me.getXY();
13141         } else {
13142             left = parseInt(me.getStyle("left"), 10) || 0;
13143             top = parseInt(me.getStyle("top"), 10) || 0;
13144             xy = [left, top];
13145         }
13146         w = me.getWidth();
13147         h = me.getHeight();
13148         if (!contentBox) {
13149             bx = {
13150                 x: xy[0],
13151                 y: xy[1],
13152                 0: xy[0],
13153                 1: xy[1],
13154                 width: w,
13155                 height: h
13156             };
13157         } else {
13158             l = getBorderWidth.call(me, "l") + getPadding.call(me, "l");
13159             r = getBorderWidth.call(me, "r") + getPadding.call(me, "r");
13160             t = getBorderWidth.call(me, "t") + getPadding.call(me, "t");
13161             b = getBorderWidth.call(me, "b") + getPadding.call(me, "b");
13162             bx = {
13163                 x: xy[0] + l,
13164                 y: xy[1] + t,
13165                 0: xy[0] + l,
13166                 1: xy[1] + t,
13167                 width: w - (l + r),
13168                 height: h - (t + b)
13169             };
13170         }
13171         bx.right = bx.x + bx.width;
13172         bx.bottom = bx.y + bx.height;
13173         return bx;
13174     },
13175
13176     
13177     move: function(direction, distance, animate) {
13178         var me = this,
13179             xy = me.getXY(),
13180             x = xy[0],
13181             y = xy[1],
13182             left = [x - distance, y],
13183             right = [x + distance, y],
13184             top = [x, y - distance],
13185             bottom = [x, y + distance],
13186             hash = {
13187                 l: left,
13188                 left: left,
13189                 r: right,
13190                 right: right,
13191                 t: top,
13192                 top: top,
13193                 up: top,
13194                 b: bottom,
13195                 bottom: bottom,
13196                 down: bottom
13197             };
13198
13199         direction = direction.toLowerCase();
13200         me.moveTo(hash[direction][0], hash[direction][1], animate);
13201     },
13202
13203     
13204     setLeftTop: function(left, top) {
13205         var me = this,
13206             style = me.dom.style;
13207         style.left = me.addUnits(left);
13208         style.top = me.addUnits(top);
13209         return me;
13210     },
13211
13212     
13213     getRegion: function() {
13214         return this.getPageBox(true);
13215     },
13216
13217     
13218     getViewRegion: function() {
13219         var me = this,
13220             isBody = me.dom === document.body,
13221             scroll, pos, top, left, width, height;
13222
13223         
13224         if (isBody) {
13225             scroll = me.getScroll();
13226             left = scroll.left;
13227             top = scroll.top;
13228             width = Ext.Element.getViewportWidth();
13229             height = Ext.Element.getViewportHeight();
13230         }
13231         else {
13232             pos = me.getXY();
13233             left = pos[0] + me.getBorderWidth('l') + me.getPadding('l');
13234             top = pos[1] + me.getBorderWidth('t') + me.getPadding('t');
13235             width = me.getWidth(true);
13236             height = me.getHeight(true);
13237         }
13238
13239         return Ext.create('Ext.util.Region', top, left + width, top + height, left);
13240     },
13241
13242     
13243     getPageBox : function(getRegion) {
13244         var me = this,
13245             el = me.dom,
13246             isDoc = el === document.body,
13247             w = isDoc ? Ext.Element.getViewWidth()  : el.offsetWidth,
13248             h = isDoc ? Ext.Element.getViewHeight() : el.offsetHeight,
13249             xy = me.getXY(),
13250             t = xy[1],
13251             r = xy[0] + w,
13252             b = xy[1] + h,
13253             l = xy[0];
13254
13255         if (getRegion) {
13256             return Ext.create('Ext.util.Region', t, r, b, l);
13257         }
13258         else {
13259             return {
13260                 left: l,
13261                 top: t,
13262                 width: w,
13263                 height: h,
13264                 right: r,
13265                 bottom: b
13266             };
13267         }
13268     },
13269
13270     
13271     setBounds: function(x, y, width, height, animate) {
13272         var me = this;
13273         if (!animate || !me.anim) {
13274             me.setSize(width, height);
13275             me.setLocation(x, y);
13276         } else {
13277             if (!Ext.isObject(animate)) {
13278                 animate = {};
13279             }
13280             me.animate(Ext.applyIf({
13281                 to: {
13282                     x: x,
13283                     y: y,
13284                     width: me.adjustWidth(width),
13285                     height: me.adjustHeight(height)
13286                 }
13287             }, animate));
13288         }
13289         return me;
13290     },
13291
13292     
13293     setRegion: function(region, animate) {
13294         return this.setBounds(region.left, region.top, region.right - region.left, region.bottom - region.top, animate);
13295     }
13296 });
13297 })();
13298
13299
13300 Ext.override(Ext.Element, {
13301     
13302     isScrollable : function(){
13303         var dom = this.dom;
13304         return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
13305     },
13306
13307     
13308     getScroll : function() {
13309         var d = this.dom, 
13310             doc = document,
13311             body = doc.body,
13312             docElement = doc.documentElement,
13313             l,
13314             t,
13315             ret;
13316
13317         if (d == doc || d == body) {
13318             if (Ext.isIE && Ext.isStrict) {
13319                 l = docElement.scrollLeft; 
13320                 t = docElement.scrollTop;
13321             } else {
13322                 l = window.pageXOffset;
13323                 t = window.pageYOffset;
13324             }
13325             ret = {
13326                 left: l || (body ? body.scrollLeft : 0), 
13327                 top : t || (body ? body.scrollTop : 0)
13328             };
13329         } else {
13330             ret = {
13331                 left: d.scrollLeft, 
13332                 top : d.scrollTop
13333             };
13334         }
13335         
13336         return ret;
13337     },
13338     
13339     
13340     scrollTo : function(side, value, animate) {
13341         
13342         var top = /top/i.test(side),
13343             me = this,
13344             dom = me.dom,
13345             obj = {},
13346             prop;
13347         if (!animate || !me.anim) {
13348             
13349             prop = 'scroll' + (top ? 'Top' : 'Left');
13350             dom[prop] = value;
13351         }
13352         else {
13353             if (!Ext.isObject(animate)) {
13354                 animate = {};
13355             }
13356             obj['scroll' + (top ? 'Top' : 'Left')] = value;
13357             me.animate(Ext.applyIf({
13358                 to: obj
13359             }, animate));
13360         }
13361         return me;
13362     },
13363
13364     
13365     scrollIntoView : function(container, hscroll) {
13366         container = Ext.getDom(container) || Ext.getBody().dom;
13367         var el = this.dom,
13368             offsets = this.getOffsetsTo(container),
13369             
13370             left = offsets[0] + container.scrollLeft,
13371             top = offsets[1] + container.scrollTop,
13372             bottom = top + el.offsetHeight,
13373             right = left + el.offsetWidth,
13374             
13375             ctClientHeight = container.clientHeight,
13376             ctScrollTop = parseInt(container.scrollTop, 10),
13377             ctScrollLeft = parseInt(container.scrollLeft, 10),
13378             ctBottom = ctScrollTop + ctClientHeight,
13379             ctRight = ctScrollLeft + container.clientWidth;
13380
13381         if (el.offsetHeight > ctClientHeight || top < ctScrollTop) {
13382             container.scrollTop = top;
13383         } else if (bottom > ctBottom) {
13384             container.scrollTop = bottom - ctClientHeight;
13385         }
13386         
13387         container.scrollTop = container.scrollTop;
13388
13389         if (hscroll !== false) {
13390             if (el.offsetWidth > container.clientWidth || left < ctScrollLeft) {
13391                 container.scrollLeft = left;
13392             }
13393             else if (right > ctRight) {
13394                 container.scrollLeft = right - container.clientWidth;
13395             }
13396             container.scrollLeft = container.scrollLeft;
13397         }
13398         return this;
13399     },
13400
13401     
13402     scrollChildIntoView : function(child, hscroll) {
13403         Ext.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
13404     },
13405
13406     
13407      scroll : function(direction, distance, animate) {
13408         if (!this.isScrollable()) {
13409             return false;
13410         }
13411         var el = this.dom,
13412             l = el.scrollLeft, t = el.scrollTop,
13413             w = el.scrollWidth, h = el.scrollHeight,
13414             cw = el.clientWidth, ch = el.clientHeight,
13415             scrolled = false, v,
13416             hash = {
13417                 l: Math.min(l + distance, w-cw),
13418                 r: v = Math.max(l - distance, 0),
13419                 t: Math.max(t - distance, 0),
13420                 b: Math.min(t + distance, h-ch)
13421             };
13422             hash.d = hash.b;
13423             hash.u = hash.t;
13424
13425         direction = direction.substr(0, 1);
13426         if ((v = hash[direction]) > -1) {
13427             scrolled = true;
13428             this.scrollTo(direction == 'l' || direction == 'r' ? 'left' : 'top', v, this.anim(animate));
13429         }
13430         return scrolled;
13431     }
13432 });
13433
13434 Ext.Element.addMethods(
13435     function() {
13436         var VISIBILITY      = "visibility",
13437             DISPLAY         = "display",
13438             HIDDEN          = "hidden",
13439             NONE            = "none",
13440             XMASKED         = Ext.baseCSSPrefix + "masked",
13441             XMASKEDRELATIVE = Ext.baseCSSPrefix + "masked-relative",
13442             data            = Ext.Element.data;
13443
13444         return {
13445             
13446             isVisible : function(deep) {
13447                 var vis = !this.isStyle(VISIBILITY, HIDDEN) && !this.isStyle(DISPLAY, NONE),
13448                     p   = this.dom.parentNode;
13449
13450                 if (deep !== true || !vis) {
13451                     return vis;
13452                 }
13453
13454                 while (p && !(/^body/i.test(p.tagName))) {
13455                     if (!Ext.fly(p, '_isVisible').isVisible()) {
13456                         return false;
13457                     }
13458                     p = p.parentNode;
13459                 }
13460                 return true;
13461             },
13462
13463             
13464             isDisplayed : function() {
13465                 return !this.isStyle(DISPLAY, NONE);
13466             },
13467
13468             
13469             enableDisplayMode : function(display) {
13470                 this.setVisibilityMode(Ext.Element.DISPLAY);
13471
13472                 if (!Ext.isEmpty(display)) {
13473                     data(this.dom, 'originalDisplay', display);
13474                 }
13475
13476                 return this;
13477             },
13478
13479             
13480             mask : function(msg, msgCls) {
13481                 var me  = this,
13482                     dom = me.dom,
13483                     setExpression = dom.style.setExpression,
13484                     dh  = Ext.DomHelper,
13485                     EXTELMASKMSG = Ext.baseCSSPrefix + "mask-msg",
13486                     el,
13487                     mask;
13488
13489                 if (!(/^body/i.test(dom.tagName) && me.getStyle('position') == 'static')) {
13490                     me.addCls(XMASKEDRELATIVE);
13491                 }
13492                 el = data(dom, 'maskMsg');
13493                 if (el) {
13494                     el.remove();
13495                 }
13496                 el = data(dom, 'mask');
13497                 if (el) {
13498                     el.remove();
13499                 }
13500
13501                 mask = dh.append(dom, {cls : Ext.baseCSSPrefix + "mask"}, true);
13502                 data(dom, 'mask', mask);
13503
13504                 me.addCls(XMASKED);
13505                 mask.setDisplayed(true);
13506
13507                 if (typeof msg == 'string') {
13508                     var mm = dh.append(dom, {cls : EXTELMASKMSG, cn:{tag:'div'}}, true);
13509                     data(dom, 'maskMsg', mm);
13510                     mm.dom.className = msgCls ? EXTELMASKMSG + " " + msgCls : EXTELMASKMSG;
13511                     mm.dom.firstChild.innerHTML = msg;
13512                     mm.setDisplayed(true);
13513                     mm.center(me);
13514                 }
13515                 
13516                 
13517                 
13518                 
13519                 
13520                 if (!Ext.supports.IncludePaddingInWidthCalculation && setExpression) {
13521                     mask.dom.style.setExpression('width', 'this.parentNode.offsetWidth + "px"');
13522                 }
13523
13524                 
13525                 
13526                 if (!Ext.supports.IncludePaddingInHeightCalculation && setExpression) {
13527                     mask.dom.style.setExpression('height', 'this.parentNode.offsetHeight + "px"');
13528                 }
13529                 
13530                 else if (Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && me.getStyle('height') == 'auto') {
13531                     mask.setSize(undefined, me.getHeight());
13532                 }
13533                 return mask;
13534             },
13535
13536             
13537             unmask : function() {
13538                 var me      = this,
13539                     dom     = me.dom,
13540                     mask    = data(dom, 'mask'),
13541                     maskMsg = data(dom, 'maskMsg');
13542
13543                 if (mask) {
13544                     
13545                     if (mask.dom.style.clearExpression) {
13546                         mask.dom.style.clearExpression('width');
13547                         mask.dom.style.clearExpression('height');
13548                     }
13549                     if (maskMsg) {
13550                         maskMsg.remove();
13551                         data(dom, 'maskMsg', undefined);
13552                     }
13553
13554                     mask.remove();
13555                     data(dom, 'mask', undefined);
13556                     me.removeCls([XMASKED, XMASKEDRELATIVE]);
13557                 }
13558             },
13559             
13560             isMasked : function() {
13561                 var me = this,
13562                     mask = data(me.dom, 'mask'),
13563                     maskMsg = data(me.dom, 'maskMsg');
13564
13565                 if (mask && mask.isVisible()) {
13566                     if (maskMsg) {
13567                         maskMsg.center(me);
13568                     }
13569                     return true;
13570                 }
13571                 return false;
13572             },
13573
13574             
13575             createShim : function() {
13576                 var el = document.createElement('iframe'),
13577                     shim;
13578
13579                 el.frameBorder = '0';
13580                 el.className = Ext.baseCSSPrefix + 'shim';
13581                 el.src = Ext.SSL_SECURE_URL;
13582                 shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
13583                 shim.autoBoxAdjust = false;
13584                 return shim;
13585             }
13586         };
13587     }()
13588 );
13589
13590 Ext.Element.addMethods({
13591     
13592     addKeyListener : function(key, fn, scope){
13593         var config;
13594         if(typeof key != 'object' || Ext.isArray(key)){
13595             config = {
13596                 key: key,
13597                 fn: fn,
13598                 scope: scope
13599             };
13600         }else{
13601             config = {
13602                 key : key.key,
13603                 shift : key.shift,
13604                 ctrl : key.ctrl,
13605                 alt : key.alt,
13606                 fn: fn,
13607                 scope: scope
13608             };
13609         }
13610         return Ext.create('Ext.util.KeyMap', this, config);
13611     },
13612
13613     
13614     addKeyMap : function(config){
13615         return Ext.create('Ext.util.KeyMap', this, config);
13616     }
13617 });
13618
13619
13620
13621 Ext.CompositeElementLite.importElementMethods();
13622
13623
13624 Ext.apply(Ext.CompositeElementLite.prototype, {
13625     addElements : function(els, root){
13626         if(!els){
13627             return this;
13628         }
13629         if(typeof els == "string"){
13630             els = Ext.Element.selectorFunction(els, root);
13631         }
13632         var yels = this.elements;
13633         Ext.each(els, function(e) {
13634             yels.push(Ext.get(e));
13635         });
13636         return this;
13637     },
13638
13639     
13640     first : function(){
13641         return this.item(0);
13642     },
13643
13644     
13645     last : function(){
13646         return this.item(this.getCount()-1);
13647     },
13648
13649     
13650     contains : function(el){
13651         return this.indexOf(el) != -1;
13652     },
13653
13654     
13655     removeElement : function(keys, removeDom){
13656         var me = this,
13657             els = this.elements,
13658             el;
13659         Ext.each(keys, function(val){
13660             if ((el = (els[val] || els[val = me.indexOf(val)]))) {
13661                 if(removeDom){
13662                     if(el.dom){
13663                         el.remove();
13664                     }else{
13665                         Ext.removeNode(el);
13666                     }
13667                 }
13668                 Ext.Array.erase(els, val, 1);
13669             }
13670         });
13671         return this;
13672     }
13673 });
13674
13675
13676 Ext.CompositeElement = Ext.extend(Ext.CompositeElementLite, {
13677
13678     constructor : function(els, root){
13679         this.elements = [];
13680         this.add(els, root);
13681     },
13682
13683     
13684     getElement : function(el){
13685         
13686         return el;
13687     },
13688
13689     
13690     transformElement : function(el){
13691         return Ext.get(el);
13692     }
13693 });
13694
13695
13696 Ext.Element.select = function(selector, unique, root){
13697     var els;
13698     if(typeof selector == "string"){
13699         els = Ext.Element.selectorFunction(selector, root);
13700     }else if(selector.length !== undefined){
13701         els = selector;
13702     }else{
13703     }
13704     return (unique === true) ? new Ext.CompositeElement(els) : new Ext.CompositeElementLite(els);
13705 };
13706
13707
13708 Ext.select = Ext.Element.select;
13709
13710
13711
13712
13713 Ext.define('Ext.util.Observable', {
13714
13715     
13716
13717     requires: ['Ext.util.Event'],
13718
13719     statics: {
13720         
13721         releaseCapture: function(o) {
13722             o.fireEvent = this.prototype.fireEvent;
13723         },
13724
13725         
13726         capture: function(o, fn, scope) {
13727             o.fireEvent = Ext.Function.createInterceptor(o.fireEvent, fn, scope);
13728         },
13729
13730         
13731         observe: function(cls, listeners) {
13732             if (cls) {
13733                 if (!cls.isObservable) {
13734                     Ext.applyIf(cls, new this());
13735                     this.capture(cls.prototype, cls.fireEvent, cls);
13736                 }
13737                 if (Ext.isObject(listeners)) {
13738                     cls.on(listeners);
13739                 }
13740                 return cls;
13741             }
13742         }
13743     },
13744
13745     
13746
13747     
13748     
13749     isObservable: true,
13750
13751     constructor: function(config) {
13752         var me = this;
13753
13754         Ext.apply(me, config);
13755         if (me.listeners) {
13756             me.on(me.listeners);
13757             delete me.listeners;
13758         }
13759         me.events = me.events || {};
13760
13761         if (me.bubbleEvents) {
13762             me.enableBubble(me.bubbleEvents);
13763         }
13764     },
13765
13766     
13767     eventOptionsRe : /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate|element|vertical|horizontal|freezeEvent)$/,
13768
13769     
13770     addManagedListener : function(item, ename, fn, scope, options) {
13771         var me = this,
13772             managedListeners = me.managedListeners = me.managedListeners || [],
13773             config;
13774
13775         if (typeof ename !== 'string') {
13776             options = ename;
13777             for (ename in options) {
13778                 if (options.hasOwnProperty(ename)) {
13779                     config = options[ename];
13780                     if (!me.eventOptionsRe.test(ename)) {
13781                         me.addManagedListener(item, ename, config.fn || config, config.scope || options.scope, config.fn ? config : options);
13782                     }
13783                 }
13784             }
13785         }
13786         else {
13787             managedListeners.push({
13788                 item: item,
13789                 ename: ename,
13790                 fn: fn,
13791                 scope: scope,
13792                 options: options
13793             });
13794
13795             item.on(ename, fn, scope, options);
13796         }
13797     },
13798
13799     
13800     removeManagedListener : function(item, ename, fn, scope) {
13801         var me = this,
13802             options,
13803             config,
13804             managedListeners,
13805             length,
13806             i;
13807
13808         if (typeof ename !== 'string') {
13809             options = ename;
13810             for (ename in options) {
13811                 if (options.hasOwnProperty(ename)) {
13812                     config = options[ename];
13813                     if (!me.eventOptionsRe.test(ename)) {
13814                         me.removeManagedListener(item, ename, config.fn || config, config.scope || options.scope);
13815                     }
13816                 }
13817             }
13818         }
13819
13820         managedListeners = me.managedListeners ? me.managedListeners.slice() : [];
13821
13822         for (i = 0, length = managedListeners.length; i < length; i++) {
13823             me.removeManagedListenerItem(false, managedListeners[i], item, ename, fn, scope);
13824         }
13825     },
13826
13827     
13828     fireEvent: function(eventName) {
13829         var name = eventName.toLowerCase(),
13830             events = this.events,
13831             event = events && events[name],
13832             bubbles = event && event.bubble;
13833
13834         return this.continueFireEvent(name, Ext.Array.slice(arguments, 1), bubbles);
13835     },
13836
13837     
13838     continueFireEvent: function(eventName, args, bubbles) {
13839         var target = this,
13840             queue, event,
13841             ret = true;
13842
13843         do {
13844             if (target.eventsSuspended === true) {
13845                 if ((queue = target.eventQueue)) {
13846                     queue.push([eventName, args, bubbles]);
13847                 }
13848                 return ret;
13849             } else {
13850                 event = target.events[eventName];
13851                 
13852                 
13853                 if (event && event != true) {
13854                     if ((ret = event.fire.apply(event, args)) === false) {
13855                         break;
13856                     }
13857                 }
13858             }
13859         } while (bubbles && (target = target.getBubbleParent()));
13860         return ret;
13861     },
13862
13863     
13864     getBubbleParent: function(){
13865         var me = this, parent = me.getBubbleTarget && me.getBubbleTarget();
13866         if (parent && parent.isObservable) {
13867             return parent;
13868         }
13869         return null;
13870     },
13871
13872     
13873     addListener: function(ename, fn, scope, options) {
13874         var me = this,
13875             config,
13876             event;
13877
13878         if (typeof ename !== 'string') {
13879             options = ename;
13880             for (ename in options) {
13881                 if (options.hasOwnProperty(ename)) {
13882                     config = options[ename];
13883                     if (!me.eventOptionsRe.test(ename)) {
13884                         me.addListener(ename, config.fn || config, config.scope || options.scope, config.fn ? config : options);
13885                     }
13886                 }
13887             }
13888         }
13889         else {
13890             ename = ename.toLowerCase();
13891             me.events[ename] = me.events[ename] || true;
13892             event = me.events[ename] || true;
13893             if (Ext.isBoolean(event)) {
13894                 me.events[ename] = event = new Ext.util.Event(me, ename);
13895             }
13896             event.addListener(fn, scope, Ext.isObject(options) ? options : {});
13897         }
13898     },
13899
13900     
13901     removeListener: function(ename, fn, scope) {
13902         var me = this,
13903             config,
13904             event,
13905             options;
13906
13907         if (typeof ename !== 'string') {
13908             options = ename;
13909             for (ename in options) {
13910                 if (options.hasOwnProperty(ename)) {
13911                     config = options[ename];
13912                     if (!me.eventOptionsRe.test(ename)) {
13913                         me.removeListener(ename, config.fn || config, config.scope || options.scope);
13914                     }
13915                 }
13916             }
13917         } else {
13918             ename = ename.toLowerCase();
13919             event = me.events[ename];
13920             if (event && event.isEvent) {
13921                 event.removeListener(fn, scope);
13922             }
13923         }
13924     },
13925
13926     
13927     clearListeners: function() {
13928         var events = this.events,
13929             event,
13930             key;
13931
13932         for (key in events) {
13933             if (events.hasOwnProperty(key)) {
13934                 event = events[key];
13935                 if (event.isEvent) {
13936                     event.clearListeners();
13937                 }
13938             }
13939         }
13940
13941         this.clearManagedListeners();
13942     },
13943
13944
13945     
13946     clearManagedListeners : function() {
13947         var managedListeners = this.managedListeners || [],
13948             i = 0,
13949             len = managedListeners.length;
13950
13951         for (; i < len; i++) {
13952             this.removeManagedListenerItem(true, managedListeners[i]);
13953         }
13954
13955         this.managedListeners = [];
13956     },
13957
13958     
13959     removeManagedListenerItem: function(isClear, managedListener, item, ename, fn, scope){
13960         if (isClear || (managedListener.item === item && managedListener.ename === ename && (!fn || managedListener.fn === fn) && (!scope || managedListener.scope === scope))) {
13961             managedListener.item.un(managedListener.ename, managedListener.fn, managedListener.scope);
13962             if (!isClear) {
13963                 Ext.Array.remove(this.managedListeners, managedListener);
13964             }
13965         }
13966     },
13967
13968
13969     
13970     addEvents: function(o) {
13971         var me = this,
13972             args,
13973             len,
13974             i;
13975
13976             me.events = me.events || {};
13977         if (Ext.isString(o)) {
13978             args = arguments;
13979             i = args.length;
13980
13981             while (i--) {
13982                 me.events[args[i]] = me.events[args[i]] || true;
13983             }
13984         } else {
13985             Ext.applyIf(me.events, o);
13986         }
13987     },
13988
13989     
13990     hasListener: function(ename) {
13991         var event = this.events[ename.toLowerCase()];
13992         return event && event.isEvent === true && event.listeners.length > 0;
13993     },
13994
13995     
13996     suspendEvents: function(queueSuspended) {
13997         this.eventsSuspended = true;
13998         if (queueSuspended && !this.eventQueue) {
13999             this.eventQueue = [];
14000         }
14001     },
14002
14003     
14004     resumeEvents: function() {
14005         var me = this,
14006             queued = me.eventQueue;
14007
14008         me.eventsSuspended = false;
14009         delete me.eventQueue;
14010
14011         if (queued) {
14012             Ext.each(queued, function(e) {
14013                 me.continueFireEvent.apply(me, e);
14014             });
14015         }
14016     },
14017
14018     
14019     relayEvents : function(origin, events, prefix) {
14020         prefix = prefix || '';
14021         var me = this,
14022             len = events.length,
14023             i = 0,
14024             oldName,
14025             newName;
14026
14027         for (; i < len; i++) {
14028             oldName = events[i].substr(prefix.length);
14029             newName = prefix + oldName;
14030             me.events[newName] = me.events[newName] || true;
14031             origin.on(oldName, me.createRelayer(newName));
14032         }
14033     },
14034
14035     
14036     createRelayer: function(newName){
14037         var me = this;
14038         return function(){
14039             return me.fireEvent.apply(me, [newName].concat(Array.prototype.slice.call(arguments, 0, -1)));
14040         };
14041     },
14042
14043     
14044     enableBubble: function(events) {
14045         var me = this;
14046         if (!Ext.isEmpty(events)) {
14047             events = Ext.isArray(events) ? events: Ext.Array.toArray(arguments);
14048             Ext.each(events,
14049             function(ename) {
14050                 ename = ename.toLowerCase();
14051                 var ce = me.events[ename] || true;
14052                 if (Ext.isBoolean(ce)) {
14053                     ce = new Ext.util.Event(me, ename);
14054                     me.events[ename] = ce;
14055                 }
14056                 ce.bubble = true;
14057             });
14058         }
14059     }
14060 }, function() {
14061
14062     this.createAlias({
14063         
14064         on: 'addListener',
14065         
14066         un: 'removeListener',
14067         
14068         mon: 'addManagedListener',
14069         
14070         mun: 'removeManagedListener'
14071     });
14072
14073     
14074     this.observeClass = this.observe;
14075
14076     Ext.apply(Ext.util.Observable.prototype, function(){
14077         
14078         
14079         
14080         function getMethodEvent(method){
14081             var e = (this.methodEvents = this.methodEvents || {})[method],
14082                 returnValue,
14083                 v,
14084                 cancel,
14085                 obj = this;
14086
14087             if (!e) {
14088                 this.methodEvents[method] = e = {};
14089                 e.originalFn = this[method];
14090                 e.methodName = method;
14091                 e.before = [];
14092                 e.after = [];
14093
14094                 var makeCall = function(fn, scope, args){
14095                     if((v = fn.apply(scope || obj, args)) !== undefined){
14096                         if (typeof v == 'object') {
14097                             if(v.returnValue !== undefined){
14098                                 returnValue = v.returnValue;
14099                             }else{
14100                                 returnValue = v;
14101                             }
14102                             cancel = !!v.cancel;
14103                         }
14104                         else
14105                             if (v === false) {
14106                                 cancel = true;
14107                             }
14108                             else {
14109                                 returnValue = v;
14110                             }
14111                     }
14112                 };
14113
14114                 this[method] = function(){
14115                     var args = Array.prototype.slice.call(arguments, 0),
14116                         b, i, len;
14117                     returnValue = v = undefined;
14118                     cancel = false;
14119
14120                     for(i = 0, len = e.before.length; i < len; i++){
14121                         b = e.before[i];
14122                         makeCall(b.fn, b.scope, args);
14123                         if (cancel) {
14124                             return returnValue;
14125                         }
14126                     }
14127
14128                     if((v = e.originalFn.apply(obj, args)) !== undefined){
14129                         returnValue = v;
14130                     }
14131
14132                     for(i = 0, len = e.after.length; i < len; i++){
14133                         b = e.after[i];
14134                         makeCall(b.fn, b.scope, args);
14135                         if (cancel) {
14136                             return returnValue;
14137                         }
14138                     }
14139                     return returnValue;
14140                 };
14141             }
14142             return e;
14143         }
14144
14145         return {
14146             
14147             
14148             
14149             beforeMethod : function(method, fn, scope){
14150                 getMethodEvent.call(this, method).before.push({
14151                     fn: fn,
14152                     scope: scope
14153                 });
14154             },
14155
14156             
14157             afterMethod : function(method, fn, scope){
14158                 getMethodEvent.call(this, method).after.push({
14159                     fn: fn,
14160                     scope: scope
14161                 });
14162             },
14163
14164             removeMethodListener: function(method, fn, scope){
14165                 var e = this.getMethodEvent(method),
14166                     i, len;
14167                 for(i = 0, len = e.before.length; i < len; i++){
14168                     if(e.before[i].fn == fn && e.before[i].scope == scope){
14169                         Ext.Array.erase(e.before, i, 1);
14170                         return;
14171                     }
14172                 }
14173                 for(i = 0, len = e.after.length; i < len; i++){
14174                     if(e.after[i].fn == fn && e.after[i].scope == scope){
14175                         Ext.Array.erase(e.after, i, 1);
14176                         return;
14177                     }
14178                 }
14179             },
14180
14181             toggleEventLogging: function(toggle) {
14182                 Ext.util.Observable[toggle ? 'capture' : 'releaseCapture'](this, function(en) {
14183                     if (Ext.isDefined(Ext.global.console)) {
14184                         Ext.global.console.log(en, arguments);
14185                     }
14186                 });
14187             }
14188         };
14189     }());
14190 });
14191
14192
14193 Ext.define('Ext.util.Animate', {
14194
14195     uses: ['Ext.fx.Manager', 'Ext.fx.Anim'],
14196
14197     
14198     animate: function(animObj) {
14199         var me = this;
14200         if (Ext.fx.Manager.hasFxBlock(me.id)) {
14201             return me;
14202         }
14203         Ext.fx.Manager.queueFx(Ext.create('Ext.fx.Anim', me.anim(animObj)));
14204         return this;
14205     },
14206
14207     
14208     anim: function(config) {
14209         if (!Ext.isObject(config)) {
14210             return (config) ? {} : false;
14211         }
14212
14213         var me = this;
14214
14215         if (config.stopAnimation) {
14216             me.stopAnimation();
14217         }
14218
14219         Ext.applyIf(config, Ext.fx.Manager.getFxDefaults(me.id));
14220
14221         return Ext.apply({
14222             target: me,
14223             paused: true
14224         }, config);
14225     },
14226
14227     
14228     stopFx: Ext.Function.alias(Ext.util.Animate, 'stopAnimation'),
14229
14230     
14231     stopAnimation: function() {
14232         Ext.fx.Manager.stopAnimation(this.id);
14233         return this;
14234     },
14235
14236     
14237     syncFx: function() {
14238         Ext.fx.Manager.setFxDefaults(this.id, {
14239             concurrent: true
14240         });
14241         return this;
14242     },
14243
14244     
14245     sequenceFx: function() {
14246         Ext.fx.Manager.setFxDefaults(this.id, {
14247             concurrent: false
14248         });
14249         return this;
14250     },
14251
14252     
14253     hasActiveFx: Ext.Function.alias(Ext.util.Animate, 'getActiveAnimation'),
14254
14255     
14256     getActiveAnimation: function() {
14257         return Ext.fx.Manager.getActiveAnimation(this.id);
14258     }
14259 }, function(){
14260     
14261     Ext.applyIf(Ext.Element.prototype, this.prototype);
14262     
14263     Ext.CompositeElementLite.importElementMethods();
14264 });
14265
14266 Ext.define('Ext.state.Provider', {
14267     mixins: {
14268         observable: 'Ext.util.Observable'
14269     },
14270     
14271     
14272     prefix: 'ext-',
14273     
14274     constructor : function(config){
14275         config = config || {};
14276         var me = this;
14277         Ext.apply(me, config);
14278         
14279         me.addEvents("statechange");
14280         me.state = {};
14281         me.mixins.observable.constructor.call(me);
14282     },
14283     
14284     
14285     get : function(name, defaultValue){
14286         return typeof this.state[name] == "undefined" ?
14287             defaultValue : this.state[name];
14288     },
14289
14290     
14291     clear : function(name){
14292         var me = this;
14293         delete me.state[name];
14294         me.fireEvent("statechange", me, name, null);
14295     },
14296
14297     
14298     set : function(name, value){
14299         var me = this;
14300         me.state[name] = value;
14301         me.fireEvent("statechange", me, name, value);
14302     },
14303
14304     
14305     decodeValue : function(value){
14306
14307         
14308         
14309         
14310         
14311         
14312         
14313         
14314
14315         var me = this,
14316             re = /^(a|n|d|b|s|o|e)\:(.*)$/,
14317             matches = re.exec(unescape(value)),
14318             all,
14319             type,
14320             value,
14321             keyValue;
14322             
14323         if(!matches || !matches[1]){
14324             return; 
14325         }
14326         
14327         type = matches[1];
14328         value = matches[2];
14329         switch (type) {
14330             case 'e':
14331                 return null;
14332             case 'n':
14333                 return parseFloat(value);
14334             case 'd':
14335                 return new Date(Date.parse(value));
14336             case 'b':
14337                 return (value == '1');
14338             case 'a':
14339                 all = [];
14340                 if(value != ''){
14341                     Ext.each(value.split('^'), function(val){
14342                         all.push(me.decodeValue(val));
14343                     }, me);
14344                 }
14345                 return all;
14346            case 'o':
14347                 all = {};
14348                 if(value != ''){
14349                     Ext.each(value.split('^'), function(val){
14350                         keyValue = val.split('=');
14351                         all[keyValue[0]] = me.decodeValue(keyValue[1]);
14352                     }, me);
14353                 }
14354                 return all;
14355            default:
14356                 return value;
14357         }
14358     },
14359
14360     
14361     encodeValue : function(value){
14362         var flat = '',
14363             i = 0,
14364             enc,
14365             len,
14366             key;
14367             
14368         if (value == null) {
14369             return 'e:1';    
14370         } else if(typeof value == 'number') {
14371             enc = 'n:' + value;
14372         } else if(typeof value == 'boolean') {
14373             enc = 'b:' + (value ? '1' : '0');
14374         } else if(Ext.isDate(value)) {
14375             enc = 'd:' + value.toGMTString();
14376         } else if(Ext.isArray(value)) {
14377             for (len = value.length; i < len; i++) {
14378                 flat += this.encodeValue(value[i]);
14379                 if (i != len - 1) {
14380                     flat += '^';
14381                 }
14382             }
14383             enc = 'a:' + flat;
14384         } else if (typeof value == 'object') {
14385             for (key in value) {
14386                 if (typeof value[key] != 'function' && value[key] !== undefined) {
14387                     flat += key + '=' + this.encodeValue(value[key]) + '^';
14388                 }
14389             }
14390             enc = 'o:' + flat.substring(0, flat.length-1);
14391         } else {
14392             enc = 's:' + value;
14393         }
14394         return escape(enc);
14395     }
14396 });
14397
14398 Ext.define('Ext.ComponentQuery', {
14399     singleton: true,
14400     uses: ['Ext.ComponentManager']
14401 }, function() {
14402
14403     var cq = this,
14404
14405         
14406         
14407         filterFnPattern = [
14408             'var r = [],',
14409                 'i = 0,',
14410                 'it = items,',
14411                 'l = it.length,',
14412                 'c;',
14413             'for (; i < l; i++) {',
14414                 'c = it[i];',
14415                 'if (c.{0}) {',
14416                    'r.push(c);',
14417                 '}',
14418             '}',
14419             'return r;'
14420         ].join(''),
14421
14422         filterItems = function(items, operation) {
14423             
14424             
14425             
14426             return operation.method.apply(this, [ items ].concat(operation.args));
14427         },
14428
14429         getItems = function(items, mode) {
14430             var result = [],
14431                 i = 0,
14432                 length = items.length,
14433                 candidate,
14434                 deep = mode !== '>';
14435                 
14436             for (; i < length; i++) {
14437                 candidate = items[i];
14438                 if (candidate.getRefItems) {
14439                     result = result.concat(candidate.getRefItems(deep));
14440                 }
14441             }
14442             return result;
14443         },
14444
14445         getAncestors = function(items) {
14446             var result = [],
14447                 i = 0,
14448                 length = items.length,
14449                 candidate;
14450             for (; i < length; i++) {
14451                 candidate = items[i];
14452                 while (!!(candidate = (candidate.ownerCt || candidate.floatParent))) {
14453                     result.push(candidate);
14454                 }
14455             }
14456             return result;
14457         },
14458
14459         
14460         filterByXType = function(items, xtype, shallow) {
14461             if (xtype === '*') {
14462                 return items.slice();
14463             }
14464             else {
14465                 var result = [],
14466                     i = 0,
14467                     length = items.length,
14468                     candidate;
14469                 for (; i < length; i++) {
14470                     candidate = items[i];
14471                     if (candidate.isXType(xtype, shallow)) {
14472                         result.push(candidate);
14473                     }
14474                 }
14475                 return result;
14476             }
14477         },
14478
14479         
14480         filterByClassName = function(items, className) {
14481             var EA = Ext.Array,
14482                 result = [],
14483                 i = 0,
14484                 length = items.length,
14485                 candidate;
14486             for (; i < length; i++) {
14487                 candidate = items[i];
14488                 if (candidate.el ? candidate.el.hasCls(className) : EA.contains(candidate.initCls(), className)) {
14489                     result.push(candidate);
14490                 }
14491             }
14492             return result;
14493         },
14494
14495         
14496         filterByAttribute = function(items, property, operator, value) {
14497             var result = [],
14498                 i = 0,
14499                 length = items.length,
14500                 candidate;
14501             for (; i < length; i++) {
14502                 candidate = items[i];
14503                 if (!value ? !!candidate[property] : (String(candidate[property]) === value)) {
14504                     result.push(candidate);
14505                 }
14506             }
14507             return result;
14508         },
14509
14510         
14511         filterById = function(items, id) {
14512             var result = [],
14513                 i = 0,
14514                 length = items.length,
14515                 candidate;
14516             for (; i < length; i++) {
14517                 candidate = items[i];
14518                 if (candidate.getItemId() === id) {
14519                     result.push(candidate);
14520                 }
14521             }
14522             return result;
14523         },
14524
14525         
14526         filterByPseudo = function(items, name, value) {
14527             return cq.pseudos[name](items, value);
14528         },
14529
14530         
14531         
14532         modeRe = /^(\s?([>\^])\s?|\s|$)/,
14533
14534         
14535         tokenRe = /^(#)?([\w\-]+|\*)(?:\((true|false)\))?/,
14536
14537         matchers = [{
14538             
14539             re: /^\.([\w\-]+)(?:\((true|false)\))?/,
14540             method: filterByXType
14541         },{
14542             
14543             re: /^(?:[\[](?:@)?([\w\-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]])/,
14544             method: filterByAttribute
14545         }, {
14546             
14547             re: /^#([\w\-]+)/,
14548             method: filterById
14549         }, {
14550             
14551             re: /^\:([\w\-]+)(?:\(((?:\{[^\}]+\})|(?:(?!\{)[^\s>\/]*?(?!\})))\))?/,
14552             method: filterByPseudo
14553         }, {
14554             
14555             re: /^(?:\{([^\}]+)\})/,
14556             method: filterFnPattern
14557         }];
14558
14559     
14560     
14561     cq.Query = Ext.extend(Object, {
14562         constructor: function(cfg) {
14563             cfg = cfg || {};
14564             Ext.apply(this, cfg);
14565         },
14566
14567         
14568         
14569         
14570         
14571         
14572         
14573         
14574         
14575         execute : function(root) {
14576             var operations = this.operations,
14577                 i = 0,
14578                 length = operations.length,
14579                 operation,
14580                 workingItems;
14581
14582             
14583             if (!root) {
14584                 workingItems = Ext.ComponentManager.all.getArray();
14585             }
14586             
14587             else if (Ext.isArray(root)) {
14588                 workingItems = root;
14589             }
14590
14591             
14592             
14593             for (; i < length; i++) {
14594                 operation = operations[i];
14595
14596                 
14597                 
14598                 
14599                 
14600                 
14601                 
14602                 if (operation.mode === '^') {
14603                     workingItems = getAncestors(workingItems || [root]);
14604                 }
14605                 else if (operation.mode) {
14606                     workingItems = getItems(workingItems || [root], operation.mode);
14607                 }
14608                 else {
14609                     workingItems = filterItems(workingItems || getItems([root]), operation);
14610                 }
14611
14612                 
14613                 
14614                 if (i === length -1) {
14615                     return workingItems;
14616                 }
14617             }
14618             return [];
14619         },
14620
14621         is: function(component) {
14622             var operations = this.operations,
14623                 components = Ext.isArray(component) ? component : [component],
14624                 originalLength = components.length,
14625                 lastOperation = operations[operations.length-1],
14626                 ln, i;
14627
14628             components = filterItems(components, lastOperation);
14629             if (components.length === originalLength) {
14630                 if (operations.length > 1) {
14631                     for (i = 0, ln = components.length; i < ln; i++) {
14632                         if (Ext.Array.indexOf(this.execute(), components[i]) === -1) {
14633                             return false;
14634                         }
14635                     }
14636                 }
14637                 return true;
14638             }
14639             return false;
14640         }
14641     });
14642
14643     Ext.apply(this, {
14644
14645         
14646         cache: {},
14647
14648         
14649         pseudos: {
14650             not: function(components, selector){
14651                 var CQ = Ext.ComponentQuery,
14652                     i = 0,
14653                     length = components.length,
14654                     results = [],
14655                     index = -1,
14656                     component;
14657                 
14658                 for(; i < length; ++i) {
14659                     component = components[i];
14660                     if (!CQ.is(component, selector)) {
14661                         results[++index] = component;
14662                     }
14663                 }
14664                 return results;
14665             },
14666             last: function(components) {
14667                 return components[components.length - 1];
14668             }
14669         },
14670
14671         
14672         query: function(selector, root) {
14673             var selectors = selector.split(','),
14674                 length = selectors.length,
14675                 i = 0,
14676                 results = [],
14677                 noDupResults = [], 
14678                 dupMatcher = {}, 
14679                 query, resultsLn, cmp;
14680
14681             for (; i < length; i++) {
14682                 selector = Ext.String.trim(selectors[i]);
14683                 query = this.cache[selector];
14684                 if (!query) {
14685                     this.cache[selector] = query = this.parse(selector);
14686                 }
14687                 results = results.concat(query.execute(root));
14688             }
14689
14690             
14691             
14692             if (length > 1) {
14693                 resultsLn = results.length;
14694                 for (i = 0; i < resultsLn; i++) {
14695                     cmp = results[i];
14696                     if (!dupMatcher[cmp.id]) {
14697                         noDupResults.push(cmp);
14698                         dupMatcher[cmp.id] = true;
14699                     }
14700                 }
14701                 results = noDupResults;
14702             }
14703             return results;
14704         },
14705
14706         
14707         is: function(component, selector) {
14708             if (!selector) {
14709                 return true;
14710             }
14711             var query = this.cache[selector];
14712             if (!query) {
14713                 this.cache[selector] = query = this.parse(selector);
14714             }
14715             return query.is(component);
14716         },
14717
14718         parse: function(selector) {
14719             var operations = [],
14720                 length = matchers.length,
14721                 lastSelector,
14722                 tokenMatch,
14723                 matchedChar,
14724                 modeMatch,
14725                 selectorMatch,
14726                 i, matcher, method;
14727
14728             
14729             
14730             
14731             while (selector && lastSelector !== selector) {
14732                 lastSelector = selector;
14733
14734                 
14735                 tokenMatch = selector.match(tokenRe);
14736
14737                 if (tokenMatch) {
14738                     matchedChar = tokenMatch[1];
14739
14740                     
14741                     if (matchedChar === '#') {
14742                         operations.push({
14743                             method: filterById,
14744                             args: [Ext.String.trim(tokenMatch[2])]
14745                         });
14746                     }
14747                     
14748                     
14749                     else if (matchedChar === '.') {
14750                         operations.push({
14751                             method: filterByClassName,
14752                             args: [Ext.String.trim(tokenMatch[2])]
14753                         });
14754                     }
14755                     
14756                     
14757                     else {
14758                         operations.push({
14759                             method: filterByXType,
14760                             args: [Ext.String.trim(tokenMatch[2]), Boolean(tokenMatch[3])]
14761                         });
14762                     }
14763
14764                     
14765                     selector = selector.replace(tokenMatch[0], '');
14766                 }
14767
14768                 
14769                 
14770                 
14771                 while (!(modeMatch = selector.match(modeRe))) {
14772                     
14773                     
14774                     for (i = 0; selector && i < length; i++) {
14775                         matcher = matchers[i];
14776                         selectorMatch = selector.match(matcher.re);
14777                         method = matcher.method;
14778
14779                         
14780                         
14781                         
14782                         if (selectorMatch) {
14783                             operations.push({
14784                                 method: Ext.isString(matcher.method)
14785                                     
14786                                     
14787                                     
14788                                     ? Ext.functionFactory('items', Ext.String.format.apply(Ext.String, [method].concat(selectorMatch.slice(1))))
14789                                     : matcher.method,
14790                                 args: selectorMatch.slice(1)
14791                             });
14792                             selector = selector.replace(selectorMatch[0], '');
14793                             break; 
14794                         }
14795                     }
14796                 }
14797
14798                 
14799                 
14800                 
14801                 
14802                 if (modeMatch[1]) { 
14803                     operations.push({
14804                         mode: modeMatch[2]||modeMatch[1]
14805                     });
14806                     selector = selector.replace(modeMatch[0], '');
14807                 }
14808             }
14809
14810             
14811             
14812             return new cq.Query({
14813                 operations: operations
14814             });
14815         }
14816     });
14817 });
14818
14819 Ext.define('Ext.util.HashMap', {
14820     mixins: {
14821         observable: 'Ext.util.Observable'
14822     },
14823
14824     
14825
14826     
14827     constructor: function(config) {
14828         config = config || {};
14829         
14830         var me = this,
14831             keyFn = config.keyFn;
14832
14833         me.addEvents(
14834             
14835             'add',
14836             
14837             'clear',
14838             
14839             'remove',
14840             
14841             'replace'
14842         );
14843
14844         me.mixins.observable.constructor.call(me, config);
14845         me.clear(true);
14846         
14847         if (keyFn) {
14848             me.getKey = keyFn;
14849         }
14850     },
14851
14852     
14853     getCount: function() {
14854         return this.length;
14855     },
14856
14857     
14858     getData: function(key, value) {
14859         
14860         if (value === undefined) {
14861             value = key;
14862             key = this.getKey(value);
14863         }
14864
14865         return [key, value];
14866     },
14867
14868     
14869     getKey: function(o) {
14870         return o.id;
14871     },
14872
14873     
14874     add: function(key, value) {
14875         var me = this,
14876             data;
14877
14878         if (arguments.length === 1) {
14879             value = key;
14880             key = me.getKey(value);
14881         }
14882
14883         if (me.containsKey(key)) {
14884             return me.replace(key, value);
14885         }
14886
14887         data = me.getData(key, value);
14888         key = data[0];
14889         value = data[1];
14890         me.map[key] = value;
14891         ++me.length;
14892         me.fireEvent('add', me, key, value);
14893         return value;
14894     },
14895
14896     
14897     replace: function(key, value) {
14898         var me = this,
14899             map = me.map,
14900             old;
14901
14902         if (!me.containsKey(key)) {
14903             me.add(key, value);
14904         }
14905         old = map[key];
14906         map[key] = value;
14907         me.fireEvent('replace', me, key, value, old);
14908         return value;
14909     },
14910
14911     
14912     remove: function(o) {
14913         var key = this.findKey(o);
14914         if (key !== undefined) {
14915             return this.removeAtKey(key);
14916         }
14917         return false;
14918     },
14919
14920     
14921     removeAtKey: function(key) {
14922         var me = this,
14923             value;
14924
14925         if (me.containsKey(key)) {
14926             value = me.map[key];
14927             delete me.map[key];
14928             --me.length;
14929             me.fireEvent('remove', me, key, value);
14930             return true;
14931         }
14932         return false;
14933     },
14934
14935     
14936     get: function(key) {
14937         return this.map[key];
14938     },
14939
14940     
14941     clear: function( initial) {
14942         var me = this;
14943         me.map = {};
14944         me.length = 0;
14945         if (initial !== true) {
14946             me.fireEvent('clear', me);
14947         }
14948         return me;
14949     },
14950
14951     
14952     containsKey: function(key) {
14953         return this.map[key] !== undefined;
14954     },
14955
14956     
14957     contains: function(value) {
14958         return this.containsKey(this.findKey(value));
14959     },
14960
14961     
14962     getKeys: function() {
14963         return this.getArray(true);
14964     },
14965
14966     
14967     getValues: function() {
14968         return this.getArray(false);
14969     },
14970
14971     
14972     getArray: function(isKey) {
14973         var arr = [],
14974             key,
14975             map = this.map;
14976         for (key in map) {
14977             if (map.hasOwnProperty(key)) {
14978                 arr.push(isKey ? key: map[key]);
14979             }
14980         }
14981         return arr;
14982     },
14983
14984     
14985     each: function(fn, scope) {
14986         
14987         var items = Ext.apply({}, this.map),
14988             key,
14989             length = this.length;
14990
14991         scope = scope || this;
14992         for (key in items) {
14993             if (items.hasOwnProperty(key)) {
14994                 if (fn.call(scope, key, items[key], length) === false) {
14995                     break;
14996                 }
14997             }
14998         }
14999         return this;
15000     },
15001
15002     
15003     clone: function() {
15004         var hash = new this.self(),
15005             map = this.map,
15006             key;
15007
15008         hash.suspendEvents();
15009         for (key in map) {
15010             if (map.hasOwnProperty(key)) {
15011                 hash.add(key, map[key]);
15012             }
15013         }
15014         hash.resumeEvents();
15015         return hash;
15016     },
15017
15018     
15019     findKey: function(value) {
15020         var key,
15021             map = this.map;
15022
15023         for (key in map) {
15024             if (map.hasOwnProperty(key) && map[key] === value) {
15025                 return key;
15026             }
15027         }
15028         return undefined;
15029     }
15030 });
15031
15032
15033 Ext.define('Ext.state.Manager', {
15034     singleton: true,
15035     requires: ['Ext.state.Provider'],
15036     constructor: function() {
15037         this.provider = Ext.create('Ext.state.Provider');
15038     },
15039     
15040     
15041     
15042     setProvider : function(stateProvider){
15043         this.provider = stateProvider;
15044     },
15045
15046     
15047     get : function(key, defaultValue){
15048         return this.provider.get(key, defaultValue);
15049     },
15050
15051     
15052      set : function(key, value){
15053         this.provider.set(key, value);
15054     },
15055
15056     
15057     clear : function(key){
15058         this.provider.clear(key);
15059     },
15060
15061     
15062     getProvider : function(){
15063         return this.provider;
15064     }
15065 });
15066
15067 Ext.define('Ext.state.Stateful', {
15068
15069     
15070
15071    mixins: {
15072         observable: 'Ext.util.Observable'
15073     },
15074
15075     requires: ['Ext.state.Manager'],
15076
15077     
15078
15079     
15080     stateful: true,
15081
15082     
15083
15084     
15085
15086     
15087     saveDelay: 100,
15088
15089     autoGenIdRe: /^((\w+-)|(ext-comp-))\d{4,}$/i,
15090
15091     constructor: function(config) {
15092         var me = this;
15093
15094         config = config || {};
15095         if (Ext.isDefined(config.stateful)) {
15096             me.stateful = config.stateful;
15097         }
15098         if (Ext.isDefined(config.saveDelay)) {
15099             me.saveDelay = config.saveDelay;
15100         }
15101         me.stateId = me.stateId || config.stateId;
15102
15103         if (!me.stateEvents) {
15104             me.stateEvents = [];
15105         }
15106         if (config.stateEvents) {
15107             me.stateEvents.concat(config.stateEvents);
15108         }
15109         this.addEvents(
15110             
15111             'beforestaterestore',
15112
15113             
15114             'staterestore',
15115
15116             
15117             'beforestatesave',
15118
15119             
15120             'statesave'
15121         );
15122         me.mixins.observable.constructor.call(me);
15123         if (me.stateful !== false) {
15124             me.initStateEvents();
15125             me.initState();
15126         }
15127     },
15128
15129     
15130     initStateEvents: function() {
15131         this.addStateEvents(this.stateEvents);
15132     },
15133
15134     
15135     addStateEvents: function(events){
15136         if (!Ext.isArray(events)) {
15137             events = [events];
15138         }
15139
15140         var me = this,
15141             i = 0,
15142             len = events.length;
15143
15144         for (; i < len; ++i) {
15145             me.on(events[i], me.onStateChange, me);
15146         }
15147     },
15148
15149     
15150     onStateChange: function(){
15151         var me = this,
15152             delay = me.saveDelay;
15153
15154         if (delay > 0) {
15155             if (!me.stateTask) {
15156                 me.stateTask = Ext.create('Ext.util.DelayedTask', me.saveState, me);
15157             }
15158             me.stateTask.delay(me.saveDelay);
15159         } else {
15160             me.saveState();
15161         }
15162     },
15163
15164     
15165     saveState: function() {
15166         var me = this,
15167             id,
15168             state;
15169
15170         if (me.stateful !== false) {
15171             id = me.getStateId();
15172             if (id) {
15173                 state = me.getState();
15174                 if (me.fireEvent('beforestatesave', me, state) !== false) {
15175                     Ext.state.Manager.set(id, state);
15176                     me.fireEvent('statesave', me, state);
15177                 }
15178             }
15179         }
15180     },
15181
15182     
15183     getState: function(){
15184         return null;
15185     },
15186
15187     
15188     applyState: function(state) {
15189         if (state) {
15190             Ext.apply(this, state);
15191         }
15192     },
15193
15194     
15195     getStateId: function() {
15196         var me = this,
15197             id = me.stateId;
15198
15199         if (!id) {
15200             id = me.autoGenIdRe.test(String(me.id)) ? null : me.id;
15201         }
15202         return id;
15203     },
15204
15205     
15206     initState: function(){
15207         var me = this,
15208             id = me.getStateId(),
15209             state;
15210
15211         if (me.stateful !== false) {
15212             if (id) {
15213                 state = Ext.state.Manager.get(id);
15214                 if (state) {
15215                     state = Ext.apply({}, state);
15216                     if (me.fireEvent('beforestaterestore', me, state) !== false) {
15217                         me.applyState(state);
15218                         me.fireEvent('staterestore', me, state);
15219                     }
15220                 }
15221             }
15222         }
15223     },
15224
15225     
15226     savePropToState: function (propName, state, stateName) {
15227         var me = this,
15228             value = me[propName],
15229             config = me.initialConfig;
15230
15231         if (me.hasOwnProperty(propName)) {
15232             if (!config || config[propName] !== value) {
15233                 if (state) {
15234                     state[stateName || propName] = value;
15235                 }
15236                 return true;
15237             }
15238         }
15239         return false;
15240     },
15241
15242     savePropsToState: function (propNames, state) {
15243         var me = this;
15244         Ext.each(propNames, function (propName) {
15245             me.savePropToState(propName, state);
15246         });
15247         return state;
15248     },
15249
15250     
15251     destroy: function(){
15252         var task = this.stateTask;
15253         if (task) {
15254             task.cancel();
15255         }
15256         this.clearListeners();
15257
15258     }
15259
15260 });
15261
15262
15263 Ext.define('Ext.AbstractManager', {
15264
15265     
15266
15267     requires: ['Ext.util.HashMap'],
15268
15269     
15270
15271     typeName: 'type',
15272
15273     constructor: function(config) {
15274         Ext.apply(this, config || {});
15275
15276         
15277         this.all = Ext.create('Ext.util.HashMap');
15278
15279         this.types = {};
15280     },
15281
15282     
15283     get : function(id) {
15284         return this.all.get(id);
15285     },
15286
15287     
15288     register: function(item) {
15289         this.all.add(item);
15290     },
15291
15292     
15293     unregister: function(item) {
15294         this.all.remove(item);
15295     },
15296
15297     
15298     registerType : function(type, cls) {
15299         this.types[type] = cls;
15300         cls[this.typeName] = type;
15301     },
15302
15303     
15304     isRegistered : function(type){
15305         return this.types[type] !== undefined;
15306     },
15307
15308     
15309     create: function(config, defaultType) {
15310         var type        = config[this.typeName] || config.type || defaultType,
15311             Constructor = this.types[type];
15312
15313
15314         return new Constructor(config);
15315     },
15316
15317     
15318     onAvailable : function(id, fn, scope){
15319         var all = this.all,
15320             item;
15321         
15322         if (all.containsKey(id)) {
15323             item = all.get(id);
15324             fn.call(scope || item, item);
15325         } else {
15326             all.on('add', function(map, key, item){
15327                 if (key == id) {
15328                     fn.call(scope || item, item);
15329                     all.un('add', fn, scope);
15330                 }
15331             });
15332         }
15333     },
15334     
15335     
15336     each: function(fn, scope){
15337         this.all.each(fn, scope || this);    
15338     },
15339     
15340     
15341     getCount: function(){
15342         return this.all.getCount();
15343     }
15344 });
15345
15346
15347 Ext.define('Ext.ComponentManager', {
15348     extend: 'Ext.AbstractManager',
15349     alternateClassName: 'Ext.ComponentMgr',
15350     
15351     singleton: true,
15352     
15353     typeName: 'xtype',
15354     
15355     
15356     create: function(component, defaultType){
15357         if (component instanceof Ext.AbstractComponent) {
15358             return component;
15359         }
15360         else if (Ext.isString(component)) {
15361             return Ext.createByAlias('widget.' + component);
15362         }
15363         else {
15364             var type = component.xtype || defaultType,
15365                 config = component;
15366             
15367             return Ext.createByAlias('widget.' + type, config);
15368         }
15369     },
15370
15371     registerType: function(type, cls) {
15372         this.types[type] = cls;
15373         cls[this.typeName] = type;
15374         cls.prototype[this.typeName] = type;
15375     }
15376 });
15377
15378 Ext.define('Ext.AbstractComponent', {
15379
15380     
15381     requires: [
15382         'Ext.ComponentQuery',
15383         'Ext.ComponentManager'
15384     ],
15385
15386     mixins: {
15387         observable: 'Ext.util.Observable',
15388         animate: 'Ext.util.Animate',
15389         state: 'Ext.state.Stateful'
15390     },
15391
15392     
15393     
15394     uses: [
15395         'Ext.PluginManager',
15396         'Ext.ComponentManager',
15397         'Ext.Element',
15398         'Ext.DomHelper',
15399         'Ext.XTemplate',
15400         'Ext.ComponentQuery',
15401         'Ext.ComponentLoader',
15402         'Ext.EventManager',
15403         'Ext.layout.Layout',
15404         'Ext.layout.component.Auto',
15405         'Ext.LoadMask',
15406         'Ext.ZIndexManager'
15407     ],
15408
15409     statics: {
15410         AUTO_ID: 1000
15411     },
15412
15413     
15414
15415     isComponent: true,
15416
15417     getAutoId: function() {
15418         return ++Ext.AbstractComponent.AUTO_ID;
15419     },
15420
15421
15422     
15423
15424     
15425
15426     
15427
15428     
15429
15430     
15431
15432     
15433
15434     
15435     renderTpl: null,
15436
15437     
15438
15439     
15440
15441     
15442
15443     
15444
15445     
15446
15447     
15448
15449     
15450
15451     
15452
15453     
15454
15455     
15456
15457     
15458     tplWriteMode: 'overwrite',
15459
15460     
15461     baseCls: Ext.baseCSSPrefix + 'component',
15462
15463     
15464
15465     
15466
15467     
15468
15469     
15470     disabledCls: Ext.baseCSSPrefix + 'item-disabled',
15471
15472     
15473     ui: 'default',
15474
15475     
15476     uiCls: [],
15477
15478     
15479
15480     
15481
15482     
15483
15484     
15485
15486     
15487
15488     
15489
15490     
15491     hidden: false,
15492
15493     
15494     disabled: false,
15495
15496     
15497
15498     
15499     draggable: false,
15500
15501     
15502     floating: false,
15503
15504     
15505     hideMode: 'display',
15506
15507     
15508
15509     
15510
15511     
15512     styleHtmlContent: false,
15513
15514     
15515     styleHtmlCls: Ext.baseCSSPrefix + 'html',
15516
15517     
15518     
15519     
15520     
15521
15522     
15523
15524     
15525     autoShow: false,
15526
15527     
15528     autoRender: false,
15529
15530     needsLayout: false,
15531
15532     
15533     allowDomMove: true,
15534
15535     
15536
15537     
15538     rendered: false,
15539
15540     
15541     componentLayoutCounter: 0,
15542
15543     weight: 0,
15544
15545     trimRe: /^\s+|\s+$/g,
15546     spacesRe: /\s+/,
15547
15548
15549     
15550     maskOnDisable: true,
15551
15552     
15553     constructor : function(config) {
15554         var me = this,
15555             i, len;
15556
15557         config = config || {};
15558         me.initialConfig = config;
15559         Ext.apply(me, config);
15560
15561         me.addEvents(
15562             
15563             'beforeactivate',
15564             
15565             'activate',
15566             
15567             'beforedeactivate',
15568             
15569             'deactivate',
15570             
15571             'added',
15572             
15573             'disable',
15574             
15575             'enable',
15576             
15577             'beforeshow',
15578             
15579             'show',
15580             
15581             'beforehide',
15582             
15583             'hide',
15584             
15585             'removed',
15586             
15587             'beforerender',
15588             
15589             'render',
15590             
15591             'afterrender',
15592             
15593             'beforedestroy',
15594             
15595             'destroy',
15596             
15597             'resize',
15598             
15599             'move'
15600         );
15601
15602         me.getId();
15603
15604         me.mons = [];
15605         me.additionalCls = [];
15606         me.renderData = me.renderData || {};
15607         me.renderSelectors = me.renderSelectors || {};
15608
15609         if (me.plugins) {
15610             me.plugins = [].concat(me.plugins);
15611             me.constructPlugins();
15612         }
15613
15614         me.initComponent();
15615
15616         
15617         Ext.ComponentManager.register(me);
15618
15619         
15620         me.mixins.observable.constructor.call(me);
15621         me.mixins.state.constructor.call(me, config);
15622
15623         
15624         this.addStateEvents('resize');
15625
15626         
15627         if (me.plugins) {
15628             me.plugins = [].concat(me.plugins);
15629             for (i = 0, len = me.plugins.length; i < len; i++) {
15630                 me.plugins[i] = me.initPlugin(me.plugins[i]);
15631             }
15632         }
15633
15634         me.loader = me.getLoader();
15635
15636         if (me.renderTo) {
15637             me.render(me.renderTo);
15638             
15639             
15640             
15641         }
15642
15643         if (me.autoShow) {
15644             me.show();
15645         }
15646
15647     },
15648
15649     initComponent: function () {
15650         
15651         
15652         this.constructPlugins();
15653     },
15654
15655     
15656     getState: function() {
15657         var me = this,
15658             layout = me.ownerCt ? (me.shadowOwnerCt || me.ownerCt).getLayout() : null,
15659             state = {
15660                 collapsed: me.collapsed
15661             },
15662             width = me.width,
15663             height = me.height,
15664             cm = me.collapseMemento,
15665             anchors;
15666
15667         
15668         
15669         if (me.collapsed && cm) {
15670             if (Ext.isDefined(cm.data.width)) {
15671                 width = cm.width;
15672             }
15673             if (Ext.isDefined(cm.data.height)) {
15674                 height = cm.height;
15675             }
15676         }
15677
15678         
15679         if (layout && me.flex) {
15680             state.flex = me.flex;
15681             if (layout.perpendicularPrefix) {
15682                 state[layout.perpendicularPrefix] = me['get' + layout.perpendicularPrefixCap]();
15683             } else {
15684             }
15685         }
15686         
15687         else if (layout && me.anchor) {
15688             state.anchor = me.anchor;
15689             anchors = me.anchor.split(' ').concat(null);
15690             if (!anchors[0]) {
15691                 if (me.width) {
15692                     state.width = width;
15693                 }
15694             }
15695             if (!anchors[1]) {
15696                 if (me.height) {
15697                     state.height = height;
15698                 }
15699             }
15700         }
15701         
15702         else {
15703             if (me.width) {
15704                 state.width = width;
15705             }
15706             if (me.height) {
15707                 state.height = height;
15708             }
15709         }
15710
15711         
15712         if (state.width == me.initialConfig.width) {
15713             delete state.width;
15714         }
15715         if (state.height == me.initialConfig.height) {
15716             delete state.height;
15717         }
15718
15719         
15720         if (layout && layout.align && (layout.align.indexOf('stretch') !== -1)) {
15721             delete state[layout.perpendicularPrefix];
15722         }
15723         return state;
15724     },
15725
15726     show: Ext.emptyFn,
15727
15728     animate: function(animObj) {
15729         var me = this,
15730             to;
15731
15732         animObj = animObj || {};
15733         to = animObj.to || {};
15734
15735         if (Ext.fx.Manager.hasFxBlock(me.id)) {
15736             return me;
15737         }
15738         
15739         if (!animObj.dynamic && (to.height || to.width)) {
15740             var curWidth = me.getWidth(),
15741                 w = curWidth,
15742                 curHeight = me.getHeight(),
15743                 h = curHeight,
15744                 needsResize = false;
15745
15746             if (to.height && to.height > curHeight) {
15747                 h = to.height;
15748                 needsResize = true;
15749             }
15750             if (to.width && to.width > curWidth) {
15751                 w = to.width;
15752                 needsResize = true;
15753             }
15754
15755             
15756             
15757             
15758             if (needsResize) {
15759                 var clearWidth = !Ext.isNumber(me.width),
15760                     clearHeight = !Ext.isNumber(me.height);
15761
15762                 me.componentLayout.childrenChanged = true;
15763                 me.setSize(w, h, me.ownerCt);
15764                 me.el.setSize(curWidth, curHeight);
15765                 if (clearWidth) {
15766                     delete me.width;
15767                 }
15768                 if (clearHeight) {
15769                     delete me.height;
15770                 }
15771             }
15772         }
15773         return me.mixins.animate.animate.apply(me, arguments);
15774     },
15775
15776     
15777     findLayoutController: function() {
15778         return this.findParentBy(function(c) {
15779             
15780             
15781             return !c.ownerCt || (c.layout.layoutBusy && !c.ownerCt.layout.layoutBusy);
15782         });
15783     },
15784
15785     onShow : function() {
15786         
15787         var needsLayout = this.needsLayout;
15788         if (Ext.isObject(needsLayout)) {
15789             this.doComponentLayout(needsLayout.width, needsLayout.height, needsLayout.isSetSize, needsLayout.ownerCt);
15790         }
15791     },
15792
15793     constructPlugin: function(plugin) {
15794         if (plugin.ptype && typeof plugin.init != 'function') {
15795             plugin.cmp = this;
15796             plugin = Ext.PluginManager.create(plugin);
15797         }
15798         else if (typeof plugin == 'string') {
15799             plugin = Ext.PluginManager.create({
15800                 ptype: plugin,
15801                 cmp: this
15802             });
15803         }
15804         return plugin;
15805     },
15806
15807     
15808     constructPlugins: function() {
15809         var me = this,
15810             plugins = me.plugins,
15811             i, len;
15812
15813         if (plugins) {
15814             for (i = 0, len = plugins.length; i < len; i++) {
15815                 
15816                 plugins[i] = me.constructPlugin(plugins[i]);
15817             }
15818         }
15819     },
15820
15821     
15822     initPlugin : function(plugin) {
15823         plugin.init(this);
15824
15825         return plugin;
15826     },
15827
15828     
15829     doAutoRender: function() {
15830         var me = this;
15831         if (me.floating) {
15832             me.render(document.body);
15833         } else {
15834             me.render(Ext.isBoolean(me.autoRender) ? Ext.getBody() : me.autoRender);
15835         }
15836     },
15837
15838     
15839     render : function(container, position) {
15840         var me = this;
15841
15842         if (!me.rendered && me.fireEvent('beforerender', me) !== false) {
15843
15844             
15845             
15846             me.rendering = true;
15847
15848             
15849             
15850             if (me.el) {
15851                 me.el = Ext.get(me.el);
15852             }
15853
15854             
15855             if (me.floating) {
15856                 me.onFloatRender();
15857             }
15858
15859             container = me.initContainer(container);
15860
15861             me.onRender(container, position);
15862
15863             
15864             
15865             me.el.setVisibilityMode(Ext.Element[me.hideMode.toUpperCase()]);
15866
15867             if (me.overCls) {
15868                 me.el.hover(me.addOverCls, me.removeOverCls, me);
15869             }
15870
15871             me.fireEvent('render', me);
15872
15873             me.initContent();
15874
15875             me.afterRender(container);
15876             me.fireEvent('afterrender', me);
15877
15878             me.initEvents();
15879
15880             if (me.hidden) {
15881                 
15882                 
15883                 
15884                 me.el.hide();
15885             }
15886
15887             if (me.disabled) {
15888                 
15889                 me.disable(true);
15890             }
15891
15892             
15893             delete me.rendering;
15894         }
15895         return me;
15896     },
15897
15898     
15899     onRender : function(container, position) {
15900         var me = this,
15901             el = me.el,
15902             styles = me.initStyles(),
15903             renderTpl, renderData, i;
15904
15905         position = me.getInsertPosition(position);
15906
15907         if (!el) {
15908             if (position) {
15909                 el = Ext.DomHelper.insertBefore(position, me.getElConfig(), true);
15910             }
15911             else {
15912                 el = Ext.DomHelper.append(container, me.getElConfig(), true);
15913             }
15914         }
15915         else if (me.allowDomMove !== false) {
15916             if (position) {
15917                 container.dom.insertBefore(el.dom, position);
15918             } else {
15919                 container.dom.appendChild(el.dom);
15920             }
15921         }
15922
15923         if (Ext.scopeResetCSS && !me.ownerCt) {
15924             
15925             if (el.dom == Ext.getBody().dom) {
15926                 el.parent().addCls(Ext.baseCSSPrefix + 'reset');
15927             }
15928             else {
15929                 
15930                 me.resetEl = el.wrap({
15931                     cls: Ext.baseCSSPrefix + 'reset'
15932                 });
15933             }
15934         }
15935
15936         me.setUI(me.ui);
15937
15938         el.addCls(me.initCls());
15939         el.setStyle(styles);
15940
15941         
15942         
15943         
15944         
15945         
15946         
15947         
15948         
15949         
15950         
15951
15952         me.el = el;
15953
15954         me.initFrame();
15955
15956         renderTpl = me.initRenderTpl();
15957         if (renderTpl) {
15958             renderData = me.initRenderData();
15959             renderTpl.append(me.getTargetEl(), renderData);
15960         }
15961
15962         me.applyRenderSelectors();
15963
15964         me.rendered = true;
15965     },
15966
15967     
15968     afterRender : function() {
15969         var me = this,
15970             pos,
15971             xy;
15972
15973         me.getComponentLayout();
15974
15975         
15976         
15977         
15978         if (me.collapsed || (!me.ownerCt || (me.height || me.width))) {
15979             me.setSize(me.width, me.height);
15980         } else {
15981             
15982             
15983             
15984             
15985             me.renderChildren();
15986         }
15987
15988         
15989         
15990         if (me.floating && (me.x === undefined || me.y === undefined)) {
15991             if (me.floatParent) {
15992                 xy = me.el.getAlignToXY(me.floatParent.getTargetEl(), 'c-c');
15993                 pos = me.floatParent.getTargetEl().translatePoints(xy[0], xy[1]);
15994             } else {
15995                 xy = me.el.getAlignToXY(me.container, 'c-c');
15996                 pos = me.container.translatePoints(xy[0], xy[1]);
15997             }
15998             me.x = me.x === undefined ? pos.left: me.x;
15999             me.y = me.y === undefined ? pos.top: me.y;
16000         }
16001
16002         if (Ext.isDefined(me.x) || Ext.isDefined(me.y)) {
16003             me.setPosition(me.x, me.y);
16004         }
16005
16006         if (me.styleHtmlContent) {
16007             me.getTargetEl().addCls(me.styleHtmlCls);
16008         }
16009     },
16010
16011     
16012     registerFloatingItem: function(cmp) {
16013         var me = this;
16014         if (!me.floatingItems) {
16015             me.floatingItems = Ext.create('Ext.ZIndexManager', me);
16016         }
16017         me.floatingItems.register(cmp);
16018     },
16019
16020     renderChildren: function () {
16021         var me = this,
16022             layout = me.getComponentLayout();
16023
16024         me.suspendLayout = true;
16025         layout.renderChildren();
16026         delete me.suspendLayout;
16027     },
16028
16029     frameCls: Ext.baseCSSPrefix + 'frame',
16030
16031     frameIdRegex: /[-]frame\d+[TMB][LCR]$/,
16032
16033     frameElementCls: {
16034         tl: [],
16035         tc: [],
16036         tr: [],
16037         ml: [],
16038         mc: [],
16039         mr: [],
16040         bl: [],
16041         bc: [],
16042         br: []
16043     },
16044
16045     frameTpl: [
16046         '<tpl if="top">',
16047             '<tpl if="left"><div id="{fgid}TL" 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>',
16048                 '<tpl if="right"><div id="{fgid}TR" 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>',
16049                     '<div id="{fgid}TC" 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>',
16050                 '<tpl if="right"></div></tpl>',
16051             '<tpl if="left"></div></tpl>',
16052         '</tpl>',
16053         '<tpl if="left"><div id="{fgid}ML" 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>',
16054             '<tpl if="right"><div id="{fgid}MR" 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>',
16055                 '<div id="{fgid}MC" class="{frameCls}-mc {baseCls}-mc {baseCls}-{ui}-mc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-mc</tpl></tpl>" role="presentation"></div>',
16056             '<tpl if="right"></div></tpl>',
16057         '<tpl if="left"></div></tpl>',
16058         '<tpl if="bottom">',
16059             '<tpl if="left"><div id="{fgid}BL" 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>',
16060                 '<tpl if="right"><div id="{fgid}BR" 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>',
16061                     '<div id="{fgid}BC" 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>',
16062                 '<tpl if="right"></div></tpl>',
16063             '<tpl if="left"></div></tpl>',
16064         '</tpl>'
16065     ],
16066
16067     frameTableTpl: [
16068         '<table><tbody>',
16069             '<tpl if="top">',
16070                 '<tr>',
16071                     '<tpl if="left"><td id="{fgid}TL" 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>',
16072                     '<td id="{fgid}TC" 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>',
16073                     '<tpl if="right"><td id="{fgid}TR" 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>',
16074                 '</tr>',
16075             '</tpl>',
16076             '<tr>',
16077                 '<tpl if="left"><td id="{fgid}ML" 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>',
16078                 '<td id="{fgid}MC" 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>',
16079                 '<tpl if="right"><td id="{fgid}MR" 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>',
16080             '</tr>',
16081             '<tpl if="bottom">',
16082                 '<tr>',
16083                     '<tpl if="left"><td id="{fgid}BL" 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>',
16084                     '<td id="{fgid}BC" 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>',
16085                     '<tpl if="right"><td id="{fgid}BR" 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>',
16086                 '</tr>',
16087             '</tpl>',
16088         '</tbody></table>'
16089     ],
16090
16091     
16092     initFrame : function() {
16093         if (Ext.supports.CSS3BorderRadius) {
16094             return false;
16095         }
16096
16097         var me = this,
16098             frameInfo = me.getFrameInfo(),
16099             frameWidth = frameInfo.width,
16100             frameTpl = me.getFrameTpl(frameInfo.table),
16101             frameGenId;
16102
16103         if (me.frame) {
16104             
16105             
16106             me.frameGenId = frameGenId = (me.frameGenId || 0) + 1;
16107             frameGenId = me.id + '-frame' + frameGenId;
16108
16109             
16110             frameTpl.insertFirst(me.el, Ext.apply({}, {
16111                 fgid:       frameGenId,
16112                 ui:         me.ui,
16113                 uiCls:      me.uiCls,
16114                 frameCls:   me.frameCls,
16115                 baseCls:    me.baseCls,
16116                 frameWidth: frameWidth,
16117                 top:        !!frameInfo.top,
16118                 left:       !!frameInfo.left,
16119                 right:      !!frameInfo.right,
16120                 bottom:     !!frameInfo.bottom
16121             }, me.getFramePositions(frameInfo)));
16122
16123             
16124             me.frameBody = me.el.down('.' + me.frameCls + '-mc');
16125
16126             
16127             me.removeChildEls(function (c) {
16128                 return c.id && me.frameIdRegex.test(c.id);
16129             });
16130
16131             
16132             Ext.each(['TL','TC','TR','ML','MC','MR','BL','BC','BR'], function (suffix) {
16133                 me.childEls.push({ name: 'frame' + suffix, id: frameGenId + suffix });
16134             });
16135         }
16136     },
16137
16138     updateFrame: function() {
16139         if (Ext.supports.CSS3BorderRadius) {
16140             return false;
16141         }
16142
16143         var me = this,
16144             wasTable = this.frameSize && this.frameSize.table,
16145             oldFrameTL = this.frameTL,
16146             oldFrameBL = this.frameBL,
16147             oldFrameML = this.frameML,
16148             oldFrameMC = this.frameMC,
16149             newMCClassName;
16150
16151         this.initFrame();
16152
16153         if (oldFrameMC) {
16154             if (me.frame) {
16155                 
16156                 delete me.frameTL;
16157                 delete me.frameTC;
16158                 delete me.frameTR;
16159                 delete me.frameML;
16160                 delete me.frameMC;
16161                 delete me.frameMR;
16162                 delete me.frameBL;
16163                 delete me.frameBC;
16164                 delete me.frameBR;
16165                 this.applyRenderSelectors();
16166
16167                 
16168                 newMCClassName = this.frameMC.dom.className;
16169
16170                 
16171                 oldFrameMC.insertAfter(this.frameMC);
16172                 this.frameMC.remove();
16173
16174                 
16175                 this.frameBody = this.frameMC = oldFrameMC;
16176
16177                 
16178                 oldFrameMC.dom.className = newMCClassName;
16179
16180                 
16181                 if (wasTable) {
16182                     me.el.query('> table')[1].remove();
16183                 }
16184                 else {
16185                     if (oldFrameTL) {
16186                         oldFrameTL.remove();
16187                     }
16188                     if (oldFrameBL) {
16189                         oldFrameBL.remove();
16190                     }
16191                     oldFrameML.remove();
16192                 }
16193             }
16194             else {
16195                 
16196
16197             }
16198         }
16199         else if (me.frame) {
16200             this.applyRenderSelectors();
16201         }
16202     },
16203
16204     getFrameInfo: function() {
16205         if (Ext.supports.CSS3BorderRadius) {
16206             return false;
16207         }
16208
16209         var me = this,
16210             left = me.el.getStyle('background-position-x'),
16211             top = me.el.getStyle('background-position-y'),
16212             info, frameInfo = false, max;
16213
16214         
16215         
16216         if (!left && !top) {
16217             info = me.el.getStyle('background-position').split(' ');
16218             left = info[0];
16219             top = info[1];
16220         }
16221
16222         
16223         
16224         
16225         if (parseInt(left, 10) >= 1000000 && parseInt(top, 10) >= 1000000) {
16226             max = Math.max;
16227
16228             frameInfo = {
16229                 
16230                 table: left.substr(0, 3) == '110',
16231
16232                 
16233                 vertical: top.substr(0, 3) == '110',
16234
16235                 
16236                 top:    max(left.substr(3, 2), left.substr(5, 2)),
16237                 right:  max(left.substr(5, 2), top.substr(3, 2)),
16238                 bottom: max(top.substr(3, 2), top.substr(5, 2)),
16239                 left:   max(top.substr(5, 2), left.substr(3, 2))
16240             };
16241
16242             frameInfo.width = max(frameInfo.top, frameInfo.right, frameInfo.bottom, frameInfo.left);
16243
16244             
16245             me.el.setStyle('background-image', 'none');
16246         }
16247
16248         
16249         
16250         if (me.frame === true && !frameInfo) {
16251         }
16252
16253         me.frame = me.frame || !!frameInfo;
16254         me.frameSize = frameInfo || false;
16255
16256         return frameInfo;
16257     },
16258
16259     getFramePositions: function(frameInfo) {
16260         var me = this,
16261             frameWidth = frameInfo.width,
16262             dock = me.dock,
16263             positions, tc, bc, ml, mr;
16264
16265         if (frameInfo.vertical) {
16266             tc = '0 -' + (frameWidth * 0) + 'px';
16267             bc = '0 -' + (frameWidth * 1) + 'px';
16268
16269             if (dock && dock == "right") {
16270                 tc = 'right -' + (frameWidth * 0) + 'px';
16271                 bc = 'right -' + (frameWidth * 1) + 'px';
16272             }
16273
16274             positions = {
16275                 tl: '0 -' + (frameWidth * 0) + 'px',
16276                 tr: '0 -' + (frameWidth * 1) + 'px',
16277                 bl: '0 -' + (frameWidth * 2) + 'px',
16278                 br: '0 -' + (frameWidth * 3) + 'px',
16279
16280                 ml: '-' + (frameWidth * 1) + 'px 0',
16281                 mr: 'right 0',
16282
16283                 tc: tc,
16284                 bc: bc
16285             };
16286         } else {
16287             ml = '-' + (frameWidth * 0) + 'px 0';
16288             mr = 'right 0';
16289
16290             if (dock && dock == "bottom") {
16291                 ml = 'left bottom';
16292                 mr = 'right bottom';
16293             }
16294
16295             positions = {
16296                 tl: '0 -' + (frameWidth * 2) + 'px',
16297                 tr: 'right -' + (frameWidth * 3) + 'px',
16298                 bl: '0 -' + (frameWidth * 4) + 'px',
16299                 br: 'right -' + (frameWidth * 5) + 'px',
16300
16301                 ml: ml,
16302                 mr: mr,
16303
16304                 tc: '0 -' + (frameWidth * 0) + 'px',
16305                 bc: '0 -' + (frameWidth * 1) + 'px'
16306             };
16307         }
16308
16309         return positions;
16310     },
16311
16312     
16313     getFrameTpl : function(table) {
16314         return table ? this.getTpl('frameTableTpl') : this.getTpl('frameTpl');
16315     },
16316
16317     
16318     initCls: function() {
16319         var me = this,
16320             cls = [];
16321
16322         cls.push(me.baseCls);
16323
16324         if (Ext.isDefined(me.cmpCls)) {
16325             if (Ext.isDefined(Ext.global.console)) {
16326                 Ext.global.console.warn('Ext.Component: cmpCls has been deprecated. Please use componentCls.');
16327             }
16328             me.componentCls = me.cmpCls;
16329             delete me.cmpCls;
16330         }
16331
16332         if (me.componentCls) {
16333             cls.push(me.componentCls);
16334         } else {
16335             me.componentCls = me.baseCls;
16336         }
16337         if (me.cls) {
16338             cls.push(me.cls);
16339             delete me.cls;
16340         }
16341
16342         return cls.concat(me.additionalCls);
16343     },
16344
16345     
16346     setUI: function(ui) {
16347         var me = this,
16348             oldUICls = Ext.Array.clone(me.uiCls),
16349             newUICls = [],
16350             classes = [],
16351             cls,
16352             i;
16353
16354         
16355         for (i = 0; i < oldUICls.length; i++) {
16356             cls = oldUICls[i];
16357
16358             classes = classes.concat(me.removeClsWithUI(cls, true));
16359             newUICls.push(cls);
16360         }
16361
16362         if (classes.length) {
16363             me.removeCls(classes);
16364         }
16365
16366         
16367         me.removeUIFromElement();
16368
16369         
16370         me.ui = ui;
16371
16372         
16373         me.addUIToElement();
16374
16375         
16376         classes = [];
16377         for (i = 0; i < newUICls.length; i++) {
16378             cls = newUICls[i];
16379             classes = classes.concat(me.addClsWithUI(cls, true));
16380         }
16381
16382         if (classes.length) {
16383             me.addCls(classes);
16384         }
16385     },
16386
16387     
16388     addClsWithUI: function(cls, skip) {
16389         var me = this,
16390             classes = [],
16391             i;
16392
16393         if (!Ext.isArray(cls)) {
16394             cls = [cls];
16395         }
16396
16397         for (i = 0; i < cls.length; i++) {
16398             if (cls[i] && !me.hasUICls(cls[i])) {
16399                 me.uiCls = Ext.Array.clone(me.uiCls);
16400                 me.uiCls.push(cls[i]);
16401
16402                 classes = classes.concat(me.addUIClsToElement(cls[i]));
16403             }
16404         }
16405
16406         if (skip !== true) {
16407             me.addCls(classes);
16408         }
16409
16410         return classes;
16411     },
16412
16413     
16414     removeClsWithUI: function(cls, skip) {
16415         var me = this,
16416             classes = [],
16417             i;
16418
16419         if (!Ext.isArray(cls)) {
16420             cls = [cls];
16421         }
16422
16423         for (i = 0; i < cls.length; i++) {
16424             if (cls[i] && me.hasUICls(cls[i])) {
16425                 me.uiCls = Ext.Array.remove(me.uiCls, cls[i]);
16426
16427                 classes = classes.concat(me.removeUIClsFromElement(cls[i]));
16428             }
16429         }
16430
16431         if (skip !== true) {
16432             me.removeCls(classes);
16433         }
16434
16435         return classes;
16436     },
16437
16438     
16439     hasUICls: function(cls) {
16440         var me = this,
16441             uiCls = me.uiCls || [];
16442
16443         return Ext.Array.contains(uiCls, cls);
16444     },
16445
16446     
16447     addUIClsToElement: function(cls, force) {
16448         var me = this,
16449             result = [],
16450             frameElementCls = me.frameElementCls;
16451
16452         result.push(Ext.baseCSSPrefix + cls);
16453         result.push(me.baseCls + '-' + cls);
16454         result.push(me.baseCls + '-' + me.ui + '-' + cls);
16455
16456         if (!force && me.frame && !Ext.supports.CSS3BorderRadius) {
16457             
16458             var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
16459                 classes, i, j, el;
16460
16461             
16462             for (i = 0; i < els.length; i++) {
16463                 el = me['frame' + els[i].toUpperCase()];
16464                 classes = [me.baseCls + '-' + me.ui + '-' + els[i], me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i]];
16465                 if (el && el.dom) {
16466                     el.addCls(classes);
16467                 } else {
16468                     for (j = 0; j < classes.length; j++) {
16469                         if (Ext.Array.indexOf(frameElementCls[els[i]], classes[j]) == -1) {
16470                             frameElementCls[els[i]].push(classes[j]);
16471                         }
16472                     }
16473                 }
16474             }
16475         }
16476
16477         me.frameElementCls = frameElementCls;
16478
16479         return result;
16480     },
16481
16482     
16483     removeUIClsFromElement: function(cls, force) {
16484         var me = this,
16485             result = [],
16486             frameElementCls = me.frameElementCls;
16487
16488         result.push(Ext.baseCSSPrefix + cls);
16489         result.push(me.baseCls + '-' + cls);
16490         result.push(me.baseCls + '-' + me.ui + '-' + cls);
16491
16492         if (!force && me.frame && !Ext.supports.CSS3BorderRadius) {
16493             
16494             var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
16495                 i, el;
16496             cls = me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i];
16497             
16498             for (i = 0; i < els.length; i++) {
16499                 el = me['frame' + els[i].toUpperCase()];
16500                 if (el && el.dom) {
16501                     el.removeCls(cls);
16502                 } else {
16503                     Ext.Array.remove(frameElementCls[els[i]], cls);
16504                 }
16505             }
16506         }
16507
16508         me.frameElementCls = frameElementCls;
16509
16510         return result;
16511     },
16512
16513     
16514     addUIToElement: function(force) {
16515         var me = this,
16516             frameElementCls = me.frameElementCls;
16517
16518         me.addCls(me.baseCls + '-' + me.ui);
16519
16520         if (me.frame && !Ext.supports.CSS3BorderRadius) {
16521             
16522             var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
16523                 i, el, cls;
16524
16525             
16526             for (i = 0; i < els.length; i++) {
16527                 el = me['frame' + els[i].toUpperCase()];
16528                 cls = me.baseCls + '-' + me.ui + '-' + els[i];
16529                 if (el) {
16530                     el.addCls(cls);
16531                 } else {
16532                     if (!Ext.Array.contains(frameElementCls[els[i]], cls)) {
16533                         frameElementCls[els[i]].push(cls);
16534                     }
16535                 }
16536             }
16537         }
16538     },
16539
16540     
16541     removeUIFromElement: function() {
16542         var me = this,
16543             frameElementCls = me.frameElementCls;
16544
16545         me.removeCls(me.baseCls + '-' + me.ui);
16546
16547         if (me.frame && !Ext.supports.CSS3BorderRadius) {
16548             
16549             var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
16550                 i, j, el, cls;
16551
16552             
16553             for (i = 0; i < els.length; i++) {
16554                 el = me['frame' + els[i].toUpperCase()];
16555                 cls = me.baseCls + '-' + me.ui + '-' + els[i];
16556
16557                 if (el) {
16558                     el.removeCls(cls);
16559                 } else {
16560                     Ext.Array.remove(frameElementCls[els[i]], cls);
16561                 }
16562             }
16563         }
16564     },
16565
16566     getElConfig : function() {
16567         if (Ext.isString(this.autoEl)) {
16568             this.autoEl = {
16569                 tag: this.autoEl
16570             };
16571         }
16572
16573         var result = this.autoEl || {tag: 'div'};
16574         result.id = this.id;
16575         return result;
16576     },
16577
16578     
16579     getInsertPosition: function(position) {
16580         
16581         if (position !== undefined) {
16582             if (Ext.isNumber(position)) {
16583                 position = this.container.dom.childNodes[position];
16584             }
16585             else {
16586                 position = Ext.getDom(position);
16587             }
16588         }
16589
16590         return position;
16591     },
16592
16593     
16594     initContainer: function(container) {
16595         var me = this;
16596
16597         
16598         
16599         
16600         if (!container && me.el) {
16601             container = me.el.dom.parentNode;
16602             me.allowDomMove = false;
16603         }
16604
16605         me.container = Ext.get(container);
16606
16607         if (me.ctCls) {
16608             me.container.addCls(me.ctCls);
16609         }
16610
16611         return me.container;
16612     },
16613
16614     
16615     initRenderData: function() {
16616         var me = this;
16617
16618         return Ext.applyIf(me.renderData, {
16619             id: me.id,
16620             ui: me.ui,
16621             uiCls: me.uiCls,
16622             baseCls: me.baseCls,
16623             componentCls: me.componentCls,
16624             frame: me.frame
16625         });
16626     },
16627
16628     
16629     getTpl: function(name) {
16630         var me = this,
16631             prototype = me.self.prototype,
16632             ownerPrototype,
16633             tpl;
16634
16635         if (me.hasOwnProperty(name)) {
16636             tpl = me[name];
16637             if (tpl && !(tpl instanceof Ext.XTemplate)) {
16638                 me[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', tpl);
16639             }
16640
16641             return me[name];
16642         }
16643
16644         if (!(prototype[name] instanceof Ext.XTemplate)) {
16645             ownerPrototype = prototype;
16646
16647             do {
16648                 if (ownerPrototype.hasOwnProperty(name)) {
16649                     tpl = ownerPrototype[name];
16650                     if (tpl && !(tpl instanceof Ext.XTemplate)) {
16651                         ownerPrototype[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', tpl);
16652                         break;
16653                     }
16654                 }
16655
16656                 ownerPrototype = ownerPrototype.superclass;
16657             } while (ownerPrototype);
16658         }
16659
16660         return prototype[name];
16661     },
16662
16663     
16664     initRenderTpl: function() {
16665         return this.getTpl('renderTpl');
16666     },
16667
16668     
16669     initStyles: function() {
16670         var style = {},
16671             me = this,
16672             Element = Ext.Element;
16673
16674         if (Ext.isString(me.style)) {
16675             style = Element.parseStyles(me.style);
16676         } else {
16677             style = Ext.apply({}, me.style);
16678         }
16679
16680         
16681         
16682         if (me.padding !== undefined) {
16683             style.padding = Element.unitizeBox((me.padding === true) ? 5 : me.padding);
16684         }
16685
16686         if (me.margin !== undefined) {
16687             style.margin = Element.unitizeBox((me.margin === true) ? 5 : me.margin);
16688         }
16689
16690         delete me.style;
16691         return style;
16692     },
16693
16694     
16695     initContent: function() {
16696         var me = this,
16697             target = me.getTargetEl(),
16698             contentEl,
16699             pre;
16700
16701         if (me.html) {
16702             target.update(Ext.DomHelper.markup(me.html));
16703             delete me.html;
16704         }
16705
16706         if (me.contentEl) {
16707             contentEl = Ext.get(me.contentEl);
16708             pre = Ext.baseCSSPrefix;
16709             contentEl.removeCls([pre + 'hidden', pre + 'hide-display', pre + 'hide-offsets', pre + 'hide-nosize']);
16710             target.appendChild(contentEl.dom);
16711         }
16712
16713         if (me.tpl) {
16714             
16715             if (!me.tpl.isTemplate) {
16716                 me.tpl = Ext.create('Ext.XTemplate', me.tpl);
16717             }
16718
16719             if (me.data) {
16720                 me.tpl[me.tplWriteMode](target, me.data);
16721                 delete me.data;
16722             }
16723         }
16724     },
16725
16726     
16727     initEvents : function() {
16728         var me = this,
16729             afterRenderEvents = me.afterRenderEvents,
16730             el,
16731             property,
16732             fn = function(listeners){
16733                 me.mon(el, listeners);
16734             };
16735         if (afterRenderEvents) {
16736             for (property in afterRenderEvents) {
16737                 if (afterRenderEvents.hasOwnProperty(property)) {
16738                     el = me[property];
16739                     if (el && el.on) {
16740                         Ext.each(afterRenderEvents[property], fn);
16741                     }
16742                 }
16743             }
16744         }
16745     },
16746
16747     
16748     addChildEls: function () {
16749         var me = this,
16750             childEls = me.childEls || (me.childEls = []);
16751
16752         childEls.push.apply(childEls, arguments);
16753     },
16754
16755     
16756     removeChildEls: function (testFn) {
16757         var me = this,
16758             old = me.childEls,
16759             keepers = (me.childEls = []),
16760             n, i, cel;
16761
16762         for (i = 0, n = old.length; i < n; ++i) {
16763             cel = old[i];
16764             if (!testFn(cel)) {
16765                 keepers.push(cel);
16766             }
16767         }
16768     },
16769
16770     
16771     applyRenderSelectors: function() {
16772         var me = this,
16773             childEls = me.childEls,
16774             selectors = me.renderSelectors,
16775             el = me.el,
16776             dom = el.dom,
16777             baseId, childName, childId, i, selector;
16778
16779         if (childEls) {
16780             baseId = me.id + '-';
16781             for (i = childEls.length; i--; ) {
16782                 childName = childId = childEls[i];
16783                 if (typeof(childName) != 'string') {
16784                     childId = childName.id || (baseId + childName.itemId);
16785                     childName = childName.name;
16786                 } else {
16787                     childId = baseId + childId;
16788                 }
16789
16790                 
16791                 
16792                 me[childName] = el.getById(childId);
16793             }
16794         }
16795
16796         
16797         
16798         
16799         if (selectors) {
16800             for (selector in selectors) {
16801                 if (selectors.hasOwnProperty(selector) && selectors[selector]) {
16802                     me[selector] = Ext.get(Ext.DomQuery.selectNode(selectors[selector], dom));
16803                 }
16804             }
16805         }
16806     },
16807
16808     
16809     is: function(selector) {
16810         return Ext.ComponentQuery.is(this, selector);
16811     },
16812
16813     
16814     up: function(selector) {
16815         var result = this.ownerCt;
16816         if (selector) {
16817             for (; result; result = result.ownerCt) {
16818                 if (Ext.ComponentQuery.is(result, selector)) {
16819                     return result;
16820                 }
16821             }
16822         }
16823         return result;
16824     },
16825
16826     
16827     nextSibling: function(selector) {
16828         var o = this.ownerCt, it, last, idx, c;
16829         if (o) {
16830             it = o.items;
16831             idx = it.indexOf(this) + 1;
16832             if (idx) {
16833                 if (selector) {
16834                     for (last = it.getCount(); idx < last; idx++) {
16835                         if ((c = it.getAt(idx)).is(selector)) {
16836                             return c;
16837                         }
16838                     }
16839                 } else {
16840                     if (idx < it.getCount()) {
16841                         return it.getAt(idx);
16842                     }
16843                 }
16844             }
16845         }
16846         return null;
16847     },
16848
16849     
16850     previousSibling: function(selector) {
16851         var o = this.ownerCt, it, idx, c;
16852         if (o) {
16853             it = o.items;
16854             idx = it.indexOf(this);
16855             if (idx != -1) {
16856                 if (selector) {
16857                     for (--idx; idx >= 0; idx--) {
16858                         if ((c = it.getAt(idx)).is(selector)) {
16859                             return c;
16860                         }
16861                     }
16862                 } else {
16863                     if (idx) {
16864                         return it.getAt(--idx);
16865                     }
16866                 }
16867             }
16868         }
16869         return null;
16870     },
16871
16872     
16873     previousNode: function(selector, includeSelf) {
16874         var node = this,
16875             result,
16876             it, len, i;
16877
16878         
16879         if (includeSelf && node.is(selector)) {
16880             return node;
16881         }
16882
16883         result = this.prev(selector);
16884         if (result) {
16885             return result;
16886         }
16887
16888         if (node.ownerCt) {
16889             for (it = node.ownerCt.items.items, i = Ext.Array.indexOf(it, node) - 1; i > -1; i--) {
16890                 if (it[i].query) {
16891                     result = it[i].query(selector);
16892                     result = result[result.length - 1];
16893                     if (result) {
16894                         return result;
16895                     }
16896                 }
16897             }
16898             return node.ownerCt.previousNode(selector, true);
16899         }
16900     },
16901
16902     
16903     nextNode: function(selector, includeSelf) {
16904         var node = this,
16905             result,
16906             it, len, i;
16907
16908         
16909         if (includeSelf && node.is(selector)) {
16910             return node;
16911         }
16912
16913         result = this.next(selector);
16914         if (result) {
16915             return result;
16916         }
16917
16918         if (node.ownerCt) {
16919             for (it = node.ownerCt.items, i = it.indexOf(node) + 1, it = it.items, len = it.length; i < len; i++) {
16920                 if (it[i].down) {
16921                     result = it[i].down(selector);
16922                     if (result) {
16923                         return result;
16924                     }
16925                 }
16926             }
16927             return node.ownerCt.nextNode(selector);
16928         }
16929     },
16930
16931     
16932     getId : function() {
16933         return this.id || (this.id = 'ext-comp-' + (this.getAutoId()));
16934     },
16935
16936     getItemId : function() {
16937         return this.itemId || this.id;
16938     },
16939
16940     
16941     getEl : function() {
16942         return this.el;
16943     },
16944
16945     
16946     getTargetEl: function() {
16947         return this.frameBody || this.el;
16948     },
16949
16950     
16951     isXType: function(xtype, shallow) {
16952         
16953         if (Ext.isFunction(xtype)) {
16954             xtype = xtype.xtype;
16955             
16956         } else if (Ext.isObject(xtype)) {
16957             xtype = xtype.statics().xtype;
16958             
16959         }
16960
16961         return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1: this.self.xtype == xtype;
16962     },
16963
16964     
16965     getXTypes: function() {
16966         var self = this.self,
16967             xtypes, parentPrototype, parentXtypes;
16968
16969         if (!self.xtypes) {
16970             xtypes = [];
16971             parentPrototype = this;
16972
16973             while (parentPrototype) {
16974                 parentXtypes = parentPrototype.xtypes;
16975
16976                 if (parentXtypes !== undefined) {
16977                     xtypes.unshift.apply(xtypes, parentXtypes);
16978                 }
16979
16980                 parentPrototype = parentPrototype.superclass;
16981             }
16982
16983             self.xtypeChain = xtypes;
16984             self.xtypes = xtypes.join('/');
16985         }
16986
16987         return self.xtypes;
16988     },
16989
16990     
16991     update : function(htmlOrData, loadScripts, cb) {
16992         var me = this;
16993
16994         if (me.tpl && !Ext.isString(htmlOrData)) {
16995             me.data = htmlOrData;
16996             if (me.rendered) {
16997                 me.tpl[me.tplWriteMode](me.getTargetEl(), htmlOrData || {});
16998             }
16999         } else {
17000             me.html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
17001             if (me.rendered) {
17002                 me.getTargetEl().update(me.html, loadScripts, cb);
17003             }
17004         }
17005
17006         if (me.rendered) {
17007             me.doComponentLayout();
17008         }
17009     },
17010
17011     
17012     setVisible : function(visible) {
17013         return this[visible ? 'show': 'hide']();
17014     },
17015
17016     
17017     isVisible: function(deep) {
17018         var me = this,
17019             child = me,
17020             visible = !me.hidden,
17021             ancestor = me.ownerCt;
17022
17023         
17024         me.hiddenAncestor = false;
17025         if (me.destroyed) {
17026             return false;
17027         }
17028
17029         if (deep && visible && me.rendered && ancestor) {
17030             while (ancestor) {
17031                 
17032                 
17033                 
17034                 
17035                 if (ancestor.hidden || (ancestor.collapsed &&
17036                         !(ancestor.getDockedItems && Ext.Array.contains(ancestor.getDockedItems(), child)))) {
17037                     
17038                     me.hiddenAncestor = ancestor;
17039                     visible = false;
17040                     break;
17041                 }
17042                 child = ancestor;
17043                 ancestor = ancestor.ownerCt;
17044             }
17045         }
17046         return visible;
17047     },
17048
17049     
17050     enable: function(silent) {
17051         var me = this;
17052
17053         if (me.rendered) {
17054             me.el.removeCls(me.disabledCls);
17055             me.el.dom.disabled = false;
17056             me.onEnable();
17057         }
17058
17059         me.disabled = false;
17060
17061         if (silent !== true) {
17062             me.fireEvent('enable', me);
17063         }
17064
17065         return me;
17066     },
17067
17068     
17069     disable: function(silent) {
17070         var me = this;
17071
17072         if (me.rendered) {
17073             me.el.addCls(me.disabledCls);
17074             me.el.dom.disabled = true;
17075             me.onDisable();
17076         }
17077
17078         me.disabled = true;
17079
17080         if (silent !== true) {
17081             me.fireEvent('disable', me);
17082         }
17083
17084         return me;
17085     },
17086
17087     
17088     onEnable: function() {
17089         if (this.maskOnDisable) {
17090             this.el.unmask();
17091         }
17092     },
17093
17094     
17095     onDisable : function() {
17096         if (this.maskOnDisable) {
17097             this.el.mask();
17098         }
17099     },
17100
17101     
17102     isDisabled : function() {
17103         return this.disabled;
17104     },
17105
17106     
17107     setDisabled : function(disabled) {
17108         return this[disabled ? 'disable': 'enable']();
17109     },
17110
17111     
17112     isHidden : function() {
17113         return this.hidden;
17114     },
17115
17116     
17117     addCls : function(className) {
17118         var me = this;
17119         if (!className) {
17120             return me;
17121         }
17122         if (!Ext.isArray(className)){
17123             className = className.replace(me.trimRe, '').split(me.spacesRe);
17124         }
17125         if (me.rendered) {
17126             me.el.addCls(className);
17127         }
17128         else {
17129             me.additionalCls = Ext.Array.unique(me.additionalCls.concat(className));
17130         }
17131         return me;
17132     },
17133
17134     
17135     addClass : function() {
17136         return this.addCls.apply(this, arguments);
17137     },
17138
17139     
17140     removeCls : function(className) {
17141         var me = this;
17142
17143         if (!className) {
17144             return me;
17145         }
17146         if (!Ext.isArray(className)){
17147             className = className.replace(me.trimRe, '').split(me.spacesRe);
17148         }
17149         if (me.rendered) {
17150             me.el.removeCls(className);
17151         }
17152         else if (me.additionalCls.length) {
17153             Ext.each(className, function(cls) {
17154                 Ext.Array.remove(me.additionalCls, cls);
17155             });
17156         }
17157         return me;
17158     },
17159
17160
17161     addOverCls: function() {
17162         var me = this;
17163         if (!me.disabled) {
17164             me.el.addCls(me.overCls);
17165         }
17166     },
17167
17168     removeOverCls: function() {
17169         this.el.removeCls(this.overCls);
17170     },
17171
17172     addListener : function(element, listeners, scope, options) {
17173         var me = this,
17174             fn,
17175             option;
17176
17177         if (Ext.isString(element) && (Ext.isObject(listeners) || options && options.element)) {
17178             if (options.element) {
17179                 fn = listeners;
17180
17181                 listeners = {};
17182                 listeners[element] = fn;
17183                 element = options.element;
17184                 if (scope) {
17185                     listeners.scope = scope;
17186                 }
17187
17188                 for (option in options) {
17189                     if (options.hasOwnProperty(option)) {
17190                         if (me.eventOptionsRe.test(option)) {
17191                             listeners[option] = options[option];
17192                         }
17193                     }
17194                 }
17195             }
17196
17197             
17198             
17199             if (me[element] && me[element].on) {
17200                 me.mon(me[element], listeners);
17201             } else {
17202                 me.afterRenderEvents = me.afterRenderEvents || {};
17203                 if (!me.afterRenderEvents[element]) {
17204                     me.afterRenderEvents[element] = [];
17205                 }
17206                 me.afterRenderEvents[element].push(listeners);
17207             }
17208         }
17209
17210         return me.mixins.observable.addListener.apply(me, arguments);
17211     },
17212
17213     
17214     removeManagedListenerItem: function(isClear, managedListener, item, ename, fn, scope){
17215         var me = this,
17216             element = managedListener.options ? managedListener.options.element : null;
17217
17218         if (element) {
17219             element = me[element];
17220             if (element && element.un) {
17221                 if (isClear || (managedListener.item === item && managedListener.ename === ename && (!fn || managedListener.fn === fn) && (!scope || managedListener.scope === scope))) {
17222                     element.un(managedListener.ename, managedListener.fn, managedListener.scope);
17223                     if (!isClear) {
17224                         Ext.Array.remove(me.managedListeners, managedListener);
17225                     }
17226                 }
17227             }
17228         } else {
17229             return me.mixins.observable.removeManagedListenerItem.apply(me, arguments);
17230         }
17231     },
17232
17233     
17234     getBubbleTarget : function() {
17235         return this.ownerCt;
17236     },
17237
17238     
17239     isFloating : function() {
17240         return this.floating;
17241     },
17242
17243     
17244     isDraggable : function() {
17245         return !!this.draggable;
17246     },
17247
17248     
17249     isDroppable : function() {
17250         return !!this.droppable;
17251     },
17252
17253     
17254     onAdded : function(container, pos) {
17255         this.ownerCt = container;
17256         this.fireEvent('added', this, container, pos);
17257     },
17258
17259     
17260     onRemoved : function() {
17261         var me = this;
17262
17263         me.fireEvent('removed', me, me.ownerCt);
17264         delete me.ownerCt;
17265     },
17266
17267     
17268     beforeDestroy : Ext.emptyFn,
17269     
17270     
17271     onResize : Ext.emptyFn,
17272
17273     
17274     setSize : function(width, height) {
17275         var me = this,
17276             layoutCollection;
17277
17278         
17279         if (Ext.isObject(width)) {
17280             height = width.height;
17281             width  = width.width;
17282         }
17283
17284         
17285         if (Ext.isNumber(width)) {
17286             width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);
17287         }
17288         if (Ext.isNumber(height)) {
17289             height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);
17290         }
17291
17292         if (!me.rendered || !me.isVisible()) {
17293             
17294             if (me.hiddenAncestor) {
17295                 layoutCollection = me.hiddenAncestor.layoutOnShow;
17296                 layoutCollection.remove(me);
17297                 layoutCollection.add(me);
17298             }
17299             me.needsLayout = {
17300                 width: width,
17301                 height: height,
17302                 isSetSize: true
17303             };
17304             if (!me.rendered) {
17305                 me.width  = (width !== undefined) ? width : me.width;
17306                 me.height = (height !== undefined) ? height : me.height;
17307             }
17308             return me;
17309         }
17310         me.doComponentLayout(width, height, true);
17311
17312         return me;
17313     },
17314
17315     isFixedWidth: function() {
17316         var me = this,
17317             layoutManagedWidth = me.layoutManagedWidth;
17318
17319         if (Ext.isDefined(me.width) || layoutManagedWidth == 1) {
17320             return true;
17321         }
17322         if (layoutManagedWidth == 2) {
17323             return false;
17324         }
17325         return (me.ownerCt && me.ownerCt.isFixedWidth());
17326     },
17327
17328     isFixedHeight: function() {
17329         var me = this,
17330             layoutManagedHeight = me.layoutManagedHeight;
17331
17332         if (Ext.isDefined(me.height) || layoutManagedHeight == 1) {
17333             return true;
17334         }
17335         if (layoutManagedHeight == 2) {
17336             return false;
17337         }
17338         return (me.ownerCt && me.ownerCt.isFixedHeight());
17339     },
17340
17341     setCalculatedSize : function(width, height, callingContainer) {
17342         var me = this,
17343             layoutCollection;
17344
17345         
17346         if (Ext.isObject(width)) {
17347             callingContainer = width.ownerCt;
17348             height = width.height;
17349             width  = width.width;
17350         }
17351
17352         
17353         if (Ext.isNumber(width)) {
17354             width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);
17355         }
17356         if (Ext.isNumber(height)) {
17357             height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);
17358         }
17359
17360         if (!me.rendered || !me.isVisible()) {
17361             
17362             if (me.hiddenAncestor) {
17363                 layoutCollection = me.hiddenAncestor.layoutOnShow;
17364                 layoutCollection.remove(me);
17365                 layoutCollection.add(me);
17366             }
17367             me.needsLayout = {
17368                 width: width,
17369                 height: height,
17370                 isSetSize: false,
17371                 ownerCt: callingContainer
17372             };
17373             return me;
17374         }
17375         me.doComponentLayout(width, height, false, callingContainer);
17376
17377         return me;
17378     },
17379
17380     
17381     doComponentLayout : function(width, height, isSetSize, callingContainer) {
17382         var me = this,
17383             componentLayout = me.getComponentLayout(),
17384             lastComponentSize = componentLayout.lastComponentSize || {
17385                 width: undefined,
17386                 height: undefined
17387             };
17388
17389         
17390         
17391         
17392         if (me.rendered && componentLayout) {
17393             
17394             if (!Ext.isDefined(width)) {
17395                 if (me.isFixedWidth()) {
17396                     width = Ext.isDefined(me.width) ? me.width : lastComponentSize.width;
17397                 }
17398             }
17399             
17400             if (!Ext.isDefined(height)) {
17401                 if (me.isFixedHeight()) {
17402                     height = Ext.isDefined(me.height) ? me.height : lastComponentSize.height;
17403                 }
17404             }
17405
17406             if (isSetSize) {
17407                 me.width = width;
17408                 me.height = height;
17409             }
17410
17411             componentLayout.layout(width, height, isSetSize, callingContainer);
17412         }
17413
17414         return me;
17415     },
17416
17417     
17418     forceComponentLayout: function () {
17419         this.doComponentLayout();
17420     },
17421
17422     
17423     setComponentLayout : function(layout) {
17424         var currentLayout = this.componentLayout;
17425         if (currentLayout && currentLayout.isLayout && currentLayout != layout) {
17426             currentLayout.setOwner(null);
17427         }
17428         this.componentLayout = layout;
17429         layout.setOwner(this);
17430     },
17431
17432     getComponentLayout : function() {
17433         var me = this;
17434
17435         if (!me.componentLayout || !me.componentLayout.isLayout) {
17436             me.setComponentLayout(Ext.layout.Layout.create(me.componentLayout, 'autocomponent'));
17437         }
17438         return me.componentLayout;
17439     },
17440
17441     
17442     afterComponentLayout: function(width, height, isSetSize, callingContainer) {
17443         var me = this,
17444             layout = me.componentLayout,
17445             oldSize = me.preLayoutSize;
17446
17447         ++me.componentLayoutCounter;
17448         if (!oldSize || ((width !== oldSize.width) || (height !== oldSize.height))) {
17449             me.fireEvent('resize', me, width, height);
17450         }
17451     },
17452
17453     
17454     beforeComponentLayout: function(width, height, isSetSize, callingContainer) {
17455         this.preLayoutSize = this.componentLayout.lastComponentSize;
17456         return true;
17457     },
17458
17459     
17460     setPosition : function(x, y) {
17461         var me = this;
17462
17463         if (Ext.isObject(x)) {
17464             y = x.y;
17465             x = x.x;
17466         }
17467
17468         if (!me.rendered) {
17469             return me;
17470         }
17471
17472         if (x !== undefined || y !== undefined) {
17473             me.el.setBox(x, y);
17474             me.onPosition(x, y);
17475             me.fireEvent('move', me, x, y);
17476         }
17477         return me;
17478     },
17479
17480     
17481     onPosition: Ext.emptyFn,
17482
17483     
17484     setWidth : function(width) {
17485         return this.setSize(width);
17486     },
17487
17488     
17489     setHeight : function(height) {
17490         return this.setSize(undefined, height);
17491     },
17492
17493     
17494     getSize : function() {
17495         return this.el.getSize();
17496     },
17497
17498     
17499     getWidth : function() {
17500         return this.el.getWidth();
17501     },
17502
17503     
17504     getHeight : function() {
17505         return this.el.getHeight();
17506     },
17507
17508     
17509     getLoader: function(){
17510         var me = this,
17511             autoLoad = me.autoLoad ? (Ext.isObject(me.autoLoad) ? me.autoLoad : {url: me.autoLoad}) : null,
17512             loader = me.loader || autoLoad;
17513
17514         if (loader) {
17515             if (!loader.isLoader) {
17516                 me.loader = Ext.create('Ext.ComponentLoader', Ext.apply({
17517                     target: me,
17518                     autoLoad: autoLoad
17519                 }, loader));
17520             } else {
17521                 loader.setTarget(me);
17522             }
17523             return me.loader;
17524
17525         }
17526         return null;
17527     },
17528
17529     
17530     setLoading : function(load, targetEl) {
17531         var me = this,
17532             config;
17533
17534         if (me.rendered) {
17535             if (load !== false && !me.collapsed) {
17536                 if (Ext.isObject(load)) {
17537                     config = load;
17538                 }
17539                 else if (Ext.isString(load)) {
17540                     config = {msg: load};
17541                 }
17542                 else {
17543                     config = {};
17544                 }
17545                 me.loadMask = me.loadMask || Ext.create('Ext.LoadMask', targetEl ? me.getTargetEl() : me.el, config);
17546                 me.loadMask.show();
17547             } else if (me.loadMask) {
17548                 Ext.destroy(me.loadMask);
17549                 me.loadMask = null;
17550             }
17551         }
17552
17553         return me.loadMask;
17554     },
17555
17556     
17557     setDocked : function(dock, layoutParent) {
17558         var me = this;
17559
17560         me.dock = dock;
17561         if (layoutParent && me.ownerCt && me.rendered) {
17562             me.ownerCt.doComponentLayout();
17563         }
17564         return me;
17565     },
17566
17567     onDestroy : function() {
17568         var me = this;
17569
17570         if (me.monitorResize && Ext.EventManager.resizeEvent) {
17571             Ext.EventManager.resizeEvent.removeListener(me.setSize, me);
17572         }
17573         
17574         Ext.destroy(
17575             me.componentLayout,
17576             me.loadMask,
17577             me.floatingItems
17578         );
17579     },
17580
17581     
17582     cleanElementRefs: function(){
17583         var me = this,
17584             i = 0,
17585             childEls = me.childEls,
17586             selectors = me.renderSelectors,
17587             selector,
17588             name,
17589             len;
17590
17591         if (me.rendered) {
17592             if (childEls) {
17593                 for (len = childEls.length; i < len; ++i) {
17594                     name = childEls[i];
17595                     if (typeof(name) != 'string') {
17596                         name = name.name;
17597                     }
17598                     delete me[name];
17599                 }
17600             }
17601
17602             if (selectors) {
17603                 for (selector in selectors) {
17604                     if (selectors.hasOwnProperty(selector)) {
17605                         delete me[selector];
17606                     }
17607                 }
17608             }
17609         }
17610         delete me.rendered;
17611         delete me.el;
17612         delete me.frameBody;
17613     },
17614
17615     
17616     destroy : function() {
17617         var me = this;
17618
17619         if (!me.isDestroyed) {
17620             if (me.fireEvent('beforedestroy', me) !== false) {
17621                 me.destroying = true;
17622                 me.beforeDestroy();
17623
17624                 if (me.floating) {
17625                     delete me.floatParent;
17626                     
17627                     
17628                     if (me.zIndexManager) {
17629                         me.zIndexManager.unregister(me);
17630                     }
17631                 } else if (me.ownerCt && me.ownerCt.remove) {
17632                     me.ownerCt.remove(me, false);
17633                 }
17634
17635                 me.onDestroy();
17636
17637                 
17638                 Ext.destroy(me.plugins);
17639
17640                 if (me.rendered) {
17641                     me.el.remove();
17642                 }
17643
17644                 me.fireEvent('destroy', me);
17645                 Ext.ComponentManager.unregister(me);
17646
17647                 me.mixins.state.destroy.call(me);
17648
17649                 me.clearListeners();
17650                 
17651                 me.cleanElementRefs();
17652                 me.destroying = false;
17653                 me.isDestroyed = true;
17654             }
17655         }
17656     },
17657
17658     
17659     getPlugin: function(pluginId) {
17660         var i = 0,
17661             plugins = this.plugins,
17662             ln = plugins.length;
17663         for (; i < ln; i++) {
17664             if (plugins[i].pluginId === pluginId) {
17665                 return plugins[i];
17666             }
17667         }
17668     },
17669
17670     
17671     isDescendantOf: function(container) {
17672         return !!this.findParentBy(function(p){
17673             return p === container;
17674         });
17675     }
17676 }, function() {
17677     this.createAlias({
17678         on: 'addListener',
17679         prev: 'previousSibling',
17680         next: 'nextSibling'
17681     });
17682 });
17683
17684
17685 Ext.define('Ext.AbstractPlugin', {
17686     disabled: false,
17687
17688     constructor: function(config) {
17689         Ext.apply(this, config);
17690     },
17691
17692     getCmp: function() {
17693         return this.cmp;
17694     },
17695
17696     
17697     init: Ext.emptyFn,
17698
17699     
17700     destroy: Ext.emptyFn,
17701
17702     
17703     enable: function() {
17704         this.disabled = false;
17705     },
17706
17707     
17708     disable: function() {
17709         this.disabled = true;
17710     }
17711 });
17712
17713 Ext.define('Ext.data.Connection', {
17714     mixins: {
17715         observable: 'Ext.util.Observable'
17716     },
17717
17718     statics: {
17719         requestId: 0
17720     },
17721
17722     url: null,
17723     async: true,
17724     method: null,
17725     username: '',
17726     password: '',
17727
17728     
17729     disableCaching: true,
17730
17731     
17732     withCredentials: false,
17733
17734     
17735     cors: false,
17736
17737     
17738     disableCachingParam: '_dc',
17739
17740     
17741     timeout : 30000,
17742
17743     
17744
17745     useDefaultHeader : true,
17746     defaultPostHeader : 'application/x-www-form-urlencoded; charset=UTF-8',
17747     useDefaultXhrHeader : true,
17748     defaultXhrHeader : 'XMLHttpRequest',
17749
17750     constructor : function(config) {
17751         config = config || {};
17752         Ext.apply(this, config);
17753
17754         this.addEvents(
17755             
17756             'beforerequest',
17757             
17758             'requestcomplete',
17759             
17760             'requestexception'
17761         );
17762         this.requests = {};
17763         this.mixins.observable.constructor.call(this);
17764     },
17765
17766     
17767     request : function(options) {
17768         options = options || {};
17769         var me = this,
17770             scope = options.scope || window,
17771             username = options.username || me.username,
17772             password = options.password || me.password || '',
17773             async,
17774             requestOptions,
17775             request,
17776             headers,
17777             xhr;
17778
17779         if (me.fireEvent('beforerequest', me, options) !== false) {
17780
17781             requestOptions = me.setOptions(options, scope);
17782
17783             if (this.isFormUpload(options) === true) {
17784                 this.upload(options.form, requestOptions.url, requestOptions.data, options);
17785                 return null;
17786             }
17787
17788             
17789             if (options.autoAbort === true || me.autoAbort) {
17790                 me.abort();
17791             }
17792
17793             
17794
17795             if ((options.cors === true || me.cors === true) && Ext.isIe && Ext.ieVersion >= 8) {
17796                 xhr = new XDomainRequest();
17797             } else {
17798                 xhr = this.getXhrInstance();
17799             }
17800
17801             async = options.async !== false ? (options.async || me.async) : false;
17802
17803             
17804             if (username) {
17805                 xhr.open(requestOptions.method, requestOptions.url, async, username, password);
17806             } else {
17807                 xhr.open(requestOptions.method, requestOptions.url, async);
17808             }
17809
17810             if (options.withCredentials === true || me.withCredentials === true) {
17811                 xhr.withCredentials = true;
17812             }
17813
17814             headers = me.setupHeaders(xhr, options, requestOptions.data, requestOptions.params);
17815
17816             
17817             request = {
17818                 id: ++Ext.data.Connection.requestId,
17819                 xhr: xhr,
17820                 headers: headers,
17821                 options: options,
17822                 async: async,
17823                 timeout: setTimeout(function() {
17824                     request.timedout = true;
17825                     me.abort(request);
17826                 }, options.timeout || me.timeout)
17827             };
17828             me.requests[request.id] = request;
17829             me.latestId = request.id;
17830             
17831             if (async) {
17832                 xhr.onreadystatechange = Ext.Function.bind(me.onStateChange, me, [request]);
17833             }
17834
17835             
17836             xhr.send(requestOptions.data);
17837             if (!async) {
17838                 return this.onComplete(request);
17839             }
17840             return request;
17841         } else {
17842             Ext.callback(options.callback, options.scope, [options, undefined, undefined]);
17843             return null;
17844         }
17845     },
17846
17847     
17848     upload: function(form, url, params, options) {
17849         form = Ext.getDom(form);
17850         options = options || {};
17851
17852         var id = Ext.id(),
17853                 frame = document.createElement('iframe'),
17854                 hiddens = [],
17855                 encoding = 'multipart/form-data',
17856                 buf = {
17857                     target: form.target,
17858                     method: form.method,
17859                     encoding: form.encoding,
17860                     enctype: form.enctype,
17861                     action: form.action
17862                 }, hiddenItem;
17863
17864         
17865         Ext.fly(frame).set({
17866             id: id,
17867             name: id,
17868             cls: Ext.baseCSSPrefix + 'hide-display',
17869             src: Ext.SSL_SECURE_URL
17870         });
17871
17872         document.body.appendChild(frame);
17873
17874         
17875         if (document.frames) {
17876            document.frames[id].name = id;
17877         }
17878
17879         Ext.fly(form).set({
17880             target: id,
17881             method: 'POST',
17882             enctype: encoding,
17883             encoding: encoding,
17884             action: url || buf.action
17885         });
17886
17887         
17888         if (params) {
17889             Ext.iterate(Ext.Object.fromQueryString(params), function(name, value){
17890                 hiddenItem = document.createElement('input');
17891                 Ext.fly(hiddenItem).set({
17892                     type: 'hidden',
17893                     value: value,
17894                     name: name
17895                 });
17896                 form.appendChild(hiddenItem);
17897                 hiddens.push(hiddenItem);
17898             });
17899         }
17900
17901         Ext.fly(frame).on('load', Ext.Function.bind(this.onUploadComplete, this, [frame, options]), null, {single: true});
17902         form.submit();
17903
17904         Ext.fly(form).set(buf);
17905         Ext.each(hiddens, function(h) {
17906             Ext.removeNode(h);
17907         });
17908     },
17909
17910     
17911     onUploadComplete: function(frame, options) {
17912         var me = this,
17913             
17914             response = {
17915                 responseText: '',
17916                 responseXML: null
17917             }, doc, firstChild;
17918
17919         try {
17920             doc = frame.contentWindow.document || frame.contentDocument || window.frames[frame.id].document;
17921             if (doc) {
17922                 if (doc.body) {
17923                     if (/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName)) { 
17924                         response.responseText = firstChild.value;
17925                     } else {
17926                         response.responseText = doc.body.innerHTML;
17927                     }
17928                 }
17929                 
17930                 response.responseXML = doc.XMLDocument || doc;
17931             }
17932         } catch (e) {
17933         }
17934
17935         me.fireEvent('requestcomplete', me, response, options);
17936
17937         Ext.callback(options.success, options.scope, [response, options]);
17938         Ext.callback(options.callback, options.scope, [options, true, response]);
17939
17940         setTimeout(function(){
17941             Ext.removeNode(frame);
17942         }, 100);
17943     },
17944
17945     
17946     isFormUpload: function(options){
17947         var form = this.getForm(options);
17948         if (form) {
17949             return (options.isUpload || (/multipart\/form-data/i).test(form.getAttribute('enctype')));
17950         }
17951         return false;
17952     },
17953
17954     
17955     getForm: function(options){
17956         return Ext.getDom(options.form) || null;
17957     },
17958
17959     
17960     setOptions: function(options, scope){
17961         var me =  this,
17962             params = options.params || {},
17963             extraParams = me.extraParams,
17964             urlParams = options.urlParams,
17965             url = options.url || me.url,
17966             jsonData = options.jsonData,
17967             method,
17968             disableCache,
17969             data;
17970
17971
17972         
17973         if (Ext.isFunction(params)) {
17974             params = params.call(scope, options);
17975         }
17976
17977         
17978         if (Ext.isFunction(url)) {
17979             url = url.call(scope, options);
17980         }
17981
17982         url = this.setupUrl(options, url);
17983
17984
17985         
17986         data = options.rawData || options.xmlData || jsonData || null;
17987         if (jsonData && !Ext.isPrimitive(jsonData)) {
17988             data = Ext.encode(data);
17989         }
17990
17991         
17992         if (Ext.isObject(params)) {
17993             params = Ext.Object.toQueryString(params);
17994         }
17995
17996         if (Ext.isObject(extraParams)) {
17997             extraParams = Ext.Object.toQueryString(extraParams);
17998         }
17999
18000         params = params + ((extraParams) ? ((params) ? '&' : '') + extraParams : '');
18001
18002         urlParams = Ext.isObject(urlParams) ? Ext.Object.toQueryString(urlParams) : urlParams;
18003
18004         params = this.setupParams(options, params);
18005
18006         
18007         method = (options.method || me.method || ((params || data) ? 'POST' : 'GET')).toUpperCase();
18008         this.setupMethod(options, method);
18009
18010
18011         disableCache = options.disableCaching !== false ? (options.disableCaching || me.disableCaching) : false;
18012         
18013         if (method === 'GET' && disableCache) {
18014             url = Ext.urlAppend(url, (options.disableCachingParam || me.disableCachingParam) + '=' + (new Date().getTime()));
18015         }
18016
18017         
18018         if ((method == 'GET' || data) && params) {
18019             url = Ext.urlAppend(url, params);
18020             params = null;
18021         }
18022
18023         
18024         if (urlParams) {
18025             url = Ext.urlAppend(url, urlParams);
18026         }
18027
18028         return {
18029             url: url,
18030             method: method,
18031             data: data || params || null
18032         };
18033     },
18034
18035     
18036     setupUrl: function(options, url){
18037         var form = this.getForm(options);
18038         if (form) {
18039             url = url || form.action;
18040         }
18041         return url;
18042     },
18043
18044
18045     
18046     setupParams: function(options, params) {
18047         var form = this.getForm(options),
18048             serializedForm;
18049         if (form && !this.isFormUpload(options)) {
18050             serializedForm = Ext.Element.serializeForm(form);
18051             params = params ? (params + '&' + serializedForm) : serializedForm;
18052         }
18053         return params;
18054     },
18055
18056     
18057     setupMethod: function(options, method){
18058         if (this.isFormUpload(options)) {
18059             return 'POST';
18060         }
18061         return method;
18062     },
18063
18064     
18065     setupHeaders: function(xhr, options, data, params){
18066         var me = this,
18067             headers = Ext.apply({}, options.headers || {}, me.defaultHeaders || {}),
18068             contentType = me.defaultPostHeader,
18069             jsonData = options.jsonData,
18070             xmlData = options.xmlData,
18071             key,
18072             header;
18073
18074         if (!headers['Content-Type'] && (data || params)) {
18075             if (data) {
18076                 if (options.rawData) {
18077                     contentType = 'text/plain';
18078                 } else {
18079                     if (xmlData && Ext.isDefined(xmlData)) {
18080                         contentType = 'text/xml';
18081                     } else if (jsonData && Ext.isDefined(jsonData)) {
18082                         contentType = 'application/json';
18083                     }
18084                 }
18085             }
18086             headers['Content-Type'] = contentType;
18087         }
18088
18089         if (me.useDefaultXhrHeader && !headers['X-Requested-With']) {
18090             headers['X-Requested-With'] = me.defaultXhrHeader;
18091         }
18092         
18093         try{
18094             for (key in headers) {
18095                 if (headers.hasOwnProperty(key)) {
18096                     header = headers[key];
18097                     xhr.setRequestHeader(key, header);
18098                 }
18099
18100             }
18101         } catch(e) {
18102             me.fireEvent('exception', key, header);
18103         }
18104         return headers;
18105     },
18106
18107     
18108     getXhrInstance: (function(){
18109         var options = [function(){
18110             return new XMLHttpRequest();
18111         }, function(){
18112             return new ActiveXObject('MSXML2.XMLHTTP.3.0');
18113         }, function(){
18114             return new ActiveXObject('MSXML2.XMLHTTP');
18115         }, function(){
18116             return new ActiveXObject('Microsoft.XMLHTTP');
18117         }], i = 0,
18118             len = options.length,
18119             xhr;
18120
18121         for(; i < len; ++i) {
18122             try{
18123                 xhr = options[i];
18124                 xhr();
18125                 break;
18126             }catch(e){}
18127         }
18128         return xhr;
18129     })(),
18130
18131     
18132     isLoading : function(request) {
18133         if (!request) {
18134             request = this.getLatest();
18135         }
18136         if (!(request && request.xhr)) {
18137             return false;
18138         }
18139         
18140         var state = request.xhr.readyState;
18141         return !(state === 0 || state == 4);
18142     },
18143
18144     
18145     abort : function(request) {
18146         var me = this;
18147         
18148         if (!request) {
18149             request = me.getLatest();
18150         }
18151
18152         if (request && me.isLoading(request)) {
18153             
18154             request.xhr.onreadystatechange = null;
18155             request.xhr.abort();
18156             me.clearTimeout(request);
18157             if (!request.timedout) {
18158                 request.aborted = true;
18159             }
18160             me.onComplete(request);
18161             me.cleanup(request);
18162         }
18163     },
18164     
18165     
18166     abortAll: function(){
18167         var requests = this.requests,
18168             id;
18169         
18170         for (id in requests) {
18171             if (requests.hasOwnProperty(id)) {
18172                 this.abort(requests[id]);
18173             }
18174         }
18175     },
18176     
18177     
18178     getLatest: function(){
18179         var id = this.latestId,
18180             request;
18181             
18182         if (id) {
18183             request = this.requests[id];
18184         }
18185         return request || null;
18186     },
18187
18188     
18189     onStateChange : function(request) {
18190         if (request.xhr.readyState == 4) {
18191             this.clearTimeout(request);
18192             this.onComplete(request);
18193             this.cleanup(request);
18194         }
18195     },
18196
18197     
18198     clearTimeout: function(request){
18199         clearTimeout(request.timeout);
18200         delete request.timeout;
18201     },
18202
18203     
18204     cleanup: function(request){
18205         request.xhr = null;
18206         delete request.xhr;
18207     },
18208
18209     
18210     onComplete : function(request) {
18211         var me = this,
18212             options = request.options,
18213             result,
18214             success,
18215             response;
18216
18217         try {
18218             result = me.parseStatus(request.xhr.status);
18219         } catch (e) {
18220             
18221             result = {
18222                 success : false,
18223                 isException : false
18224             };
18225         }
18226         success = result.success;
18227
18228         if (success) {
18229             response = me.createResponse(request);
18230             me.fireEvent('requestcomplete', me, response, options);
18231             Ext.callback(options.success, options.scope, [response, options]);
18232         } else {
18233             if (result.isException || request.aborted || request.timedout) {
18234                 response = me.createException(request);
18235             } else {
18236                 response = me.createResponse(request);
18237             }
18238             me.fireEvent('requestexception', me, response, options);
18239             Ext.callback(options.failure, options.scope, [response, options]);
18240         }
18241         Ext.callback(options.callback, options.scope, [options, success, response]);
18242         delete me.requests[request.id];
18243         return response;
18244     },
18245
18246     
18247     parseStatus: function(status) {
18248         
18249         status = status == 1223 ? 204 : status;
18250
18251         var success = (status >= 200 && status < 300) || status == 304,
18252             isException = false;
18253
18254         if (!success) {
18255             switch (status) {
18256                 case 12002:
18257                 case 12029:
18258                 case 12030:
18259                 case 12031:
18260                 case 12152:
18261                 case 13030:
18262                     isException = true;
18263                     break;
18264             }
18265         }
18266         return {
18267             success: success,
18268             isException: isException
18269         };
18270     },
18271
18272     
18273     createResponse : function(request) {
18274         var xhr = request.xhr,
18275             headers = {},
18276             lines = xhr.getAllResponseHeaders().replace(/\r\n/g, '\n').split('\n'),
18277             count = lines.length,
18278             line, index, key, value, response;
18279
18280         while (count--) {
18281             line = lines[count];
18282             index = line.indexOf(':');
18283             if(index >= 0) {
18284                 key = line.substr(0, index).toLowerCase();
18285                 if (line.charAt(index + 1) == ' ') {
18286                     ++index;
18287                 }
18288                 headers[key] = line.substr(index + 1);
18289             }
18290         }
18291
18292         request.xhr = null;
18293         delete request.xhr;
18294
18295         response = {
18296             request: request,
18297             requestId : request.id,
18298             status : xhr.status,
18299             statusText : xhr.statusText,
18300             getResponseHeader : function(header){ return headers[header.toLowerCase()]; },
18301             getAllResponseHeaders : function(){ return headers; },
18302             responseText : xhr.responseText,
18303             responseXML : xhr.responseXML
18304         };
18305
18306         
18307         
18308         xhr = null;
18309         return response;
18310     },
18311
18312     
18313     createException : function(request) {
18314         return {
18315             request : request,
18316             requestId : request.id,
18317             status : request.aborted ? -1 : 0,
18318             statusText : request.aborted ? 'transaction aborted' : 'communication failure',
18319             aborted: request.aborted,
18320             timedout: request.timedout
18321         };
18322     }
18323 });
18324
18325
18326 Ext.define('Ext.Ajax', {
18327     extend: 'Ext.data.Connection',
18328     singleton: true,
18329
18330     
18331     
18332     
18333     
18334     
18335     
18336
18337     
18338
18339     
18340     
18341     
18342     
18343     
18344     
18345
18346     
18347     autoAbort : false
18348 });
18349
18350 Ext.define('Ext.ElementLoader', {
18351
18352     
18353
18354     mixins: {
18355         observable: 'Ext.util.Observable'
18356     },
18357
18358     uses: [
18359         'Ext.data.Connection',
18360         'Ext.Ajax'
18361     ],
18362
18363     statics: {
18364         Renderer: {
18365             Html: function(loader, response, active){
18366                 loader.getTarget().update(response.responseText, active.scripts === true);
18367                 return true;
18368             }
18369         }
18370     },
18371
18372     
18373
18374     
18375     url: null,
18376
18377     
18378     params: null,
18379
18380     
18381     baseParams: null,
18382
18383     
18384     autoLoad: false,
18385
18386     
18387     target: null,
18388
18389     
18390     loadMask: false,
18391
18392     
18393     ajaxOptions: null,
18394
18395     
18396     scripts: false,
18397
18398     
18399
18400     
18401
18402     
18403
18404     
18405
18406     
18407
18408     isLoader: true,
18409
18410     constructor: function(config) {
18411         var me = this,
18412             autoLoad;
18413
18414         config = config || {};
18415         Ext.apply(me, config);
18416         me.setTarget(me.target);
18417         me.addEvents(
18418             
18419             'beforeload',
18420
18421             
18422             'exception',
18423
18424             
18425             'load'
18426         );
18427
18428         
18429         me.mixins.observable.constructor.call(me);
18430
18431         if (me.autoLoad) {
18432             autoLoad = me.autoLoad;
18433             if (autoLoad === true) {
18434                 autoLoad = {};
18435             }
18436             me.load(autoLoad);
18437         }
18438     },
18439
18440     
18441     setTarget: function(target){
18442         var me = this;
18443         target = Ext.get(target);
18444         if (me.target && me.target != target) {
18445             me.abort();
18446         }
18447         me.target = target;
18448     },
18449
18450     
18451     getTarget: function(){
18452         return this.target || null;
18453     },
18454
18455     
18456     abort: function(){
18457         var active = this.active;
18458         if (active !== undefined) {
18459             Ext.Ajax.abort(active.request);
18460             if (active.mask) {
18461                 this.removeMask();
18462             }
18463             delete this.active;
18464         }
18465     },
18466
18467     
18468     removeMask: function(){
18469         this.target.unmask();
18470     },
18471
18472     
18473     addMask: function(mask){
18474         this.target.mask(mask === true ? null : mask);
18475     },
18476
18477     
18478     load: function(options) {
18479
18480         options = Ext.apply({}, options);
18481
18482         var me = this,
18483             target = me.target,
18484             mask = Ext.isDefined(options.loadMask) ? options.loadMask : me.loadMask,
18485             params = Ext.apply({}, options.params),
18486             ajaxOptions = Ext.apply({}, options.ajaxOptions),
18487             callback = options.callback || me.callback,
18488             scope = options.scope || me.scope || me,
18489             request;
18490
18491         Ext.applyIf(ajaxOptions, me.ajaxOptions);
18492         Ext.applyIf(options, ajaxOptions);
18493
18494         Ext.applyIf(params, me.params);
18495         Ext.apply(params, me.baseParams);
18496
18497         Ext.applyIf(options, {
18498             url: me.url
18499         });
18500
18501
18502         Ext.apply(options, {
18503             scope: me,
18504             params: params,
18505             callback: me.onComplete
18506         });
18507
18508         if (me.fireEvent('beforeload', me, options) === false) {
18509             return;
18510         }
18511
18512         if (mask) {
18513             me.addMask(mask);
18514         }
18515
18516         request = Ext.Ajax.request(options);
18517         me.active = {
18518             request: request,
18519             options: options,
18520             mask: mask,
18521             scope: scope,
18522             callback: callback,
18523             success: options.success || me.success,
18524             failure: options.failure || me.failure,
18525             renderer: options.renderer || me.renderer,
18526             scripts: Ext.isDefined(options.scripts) ? options.scripts : me.scripts
18527         };
18528         me.setOptions(me.active, options);
18529     },
18530
18531     
18532     setOptions: Ext.emptyFn,
18533
18534     
18535     onComplete: function(options, success, response) {
18536         var me = this,
18537             active = me.active,
18538             scope = active.scope,
18539             renderer = me.getRenderer(active.renderer);
18540
18541
18542         if (success) {
18543             success = renderer.call(me, me, response, active);
18544         }
18545
18546         if (success) {
18547             Ext.callback(active.success, scope, [me, response, options]);
18548             me.fireEvent('load', me, response, options);
18549         } else {
18550             Ext.callback(active.failure, scope, [me, response, options]);
18551             me.fireEvent('exception', me, response, options);
18552         }
18553         Ext.callback(active.callback, scope, [me, success, response, options]);
18554
18555         if (active.mask) {
18556             me.removeMask();
18557         }
18558
18559         delete me.active;
18560     },
18561
18562     
18563     getRenderer: function(renderer){
18564         if (Ext.isFunction(renderer)) {
18565             return renderer;
18566         }
18567         return this.statics().Renderer.Html;
18568     },
18569
18570     
18571     startAutoRefresh: function(interval, options){
18572         var me = this;
18573         me.stopAutoRefresh();
18574         me.autoRefresh = setInterval(function(){
18575             me.load(options);
18576         }, interval);
18577     },
18578
18579     
18580     stopAutoRefresh: function(){
18581         clearInterval(this.autoRefresh);
18582         delete this.autoRefresh;
18583     },
18584
18585     
18586     isAutoRefreshing: function(){
18587         return Ext.isDefined(this.autoRefresh);
18588     },
18589
18590     
18591     destroy: function(){
18592         var me = this;
18593         me.stopAutoRefresh();
18594         delete me.target;
18595         me.abort();
18596         me.clearListeners();
18597     }
18598 });
18599
18600
18601 Ext.define('Ext.ComponentLoader', {
18602
18603     
18604
18605     extend: 'Ext.ElementLoader',
18606
18607     statics: {
18608         Renderer: {
18609             Data: function(loader, response, active){
18610                 var success = true;
18611                 try {
18612                     loader.getTarget().update(Ext.decode(response.responseText));
18613                 } catch (e) {
18614                     success = false;
18615                 }
18616                 return success;
18617             },
18618
18619             Component: function(loader, response, active){
18620                 var success = true,
18621                     target = loader.getTarget(),
18622                     items = [];
18623
18624
18625                 try {
18626                     items = Ext.decode(response.responseText);
18627                 } catch (e) {
18628                     success = false;
18629                 }
18630
18631                 if (success) {
18632                     if (active.removeAll) {
18633                         target.removeAll();
18634                     }
18635                     target.add(items);
18636                 }
18637                 return success;
18638             }
18639         }
18640     },
18641
18642     
18643
18644     
18645     target: null,
18646
18647     
18648     loadMask: false,
18649
18650     
18651
18652     
18653     renderer: 'html',
18654
18655     
18656     setTarget: function(target){
18657         var me = this;
18658
18659         if (Ext.isString(target)) {
18660             target = Ext.getCmp(target);
18661         }
18662
18663         if (me.target && me.target != target) {
18664             me.abort();
18665         }
18666         me.target = target;
18667     },
18668
18669     
18670     removeMask: function(){
18671         this.target.setLoading(false);
18672     },
18673
18674     
18675     addMask: function(mask){
18676         this.target.setLoading(mask);
18677     },
18678
18679     
18680
18681     setOptions: function(active, options){
18682         active.removeAll = Ext.isDefined(options.removeAll) ? options.removeAll : this.removeAll;
18683     },
18684
18685     
18686     getRenderer: function(renderer){
18687         if (Ext.isFunction(renderer)) {
18688             return renderer;
18689         }
18690
18691         var renderers = this.statics().Renderer;
18692         switch (renderer) {
18693             case 'component':
18694                 return renderers.Component;
18695             case 'data':
18696                 return renderers.Data;
18697             default:
18698                 return Ext.ElementLoader.Renderer.Html;
18699         }
18700     }
18701 });
18702
18703
18704 Ext.define('Ext.data.Association', {
18705     
18706
18707     
18708
18709     
18710     primaryKey: 'id',
18711
18712     
18713     
18714     
18715
18716     defaultReaderType: 'json',
18717
18718     statics: {
18719         create: function(association){
18720             if (!association.isAssociation) {
18721                 if (Ext.isString(association)) {
18722                     association = {
18723                         type: association
18724                     };
18725                 }
18726
18727                 switch (association.type) {
18728                     case 'belongsTo':
18729                         return Ext.create('Ext.data.BelongsToAssociation', association);
18730                     case 'hasMany':
18731                         return Ext.create('Ext.data.HasManyAssociation', association);
18732                     
18733
18734
18735                     default:
18736                 }
18737             }
18738             return association;
18739         }
18740     },
18741
18742     
18743     constructor: function(config) {
18744         Ext.apply(this, config);
18745
18746         var types           = Ext.ModelManager.types,
18747             ownerName       = config.ownerModel,
18748             associatedName  = config.associatedModel,
18749             ownerModel      = types[ownerName],
18750             associatedModel = types[associatedName],
18751             ownerProto;
18752
18753
18754         this.ownerModel = ownerModel;
18755         this.associatedModel = associatedModel;
18756
18757         
18758
18759         
18760
18761         Ext.applyIf(this, {
18762             ownerName : ownerName,
18763             associatedName: associatedName
18764         });
18765     },
18766
18767     
18768     getReader: function(){
18769         var me = this,
18770             reader = me.reader,
18771             model = me.associatedModel;
18772
18773         if (reader) {
18774             if (Ext.isString(reader)) {
18775                 reader = {
18776                     type: reader
18777                 };
18778             }
18779             if (reader.isReader) {
18780                 reader.setModel(model);
18781             } else {
18782                 Ext.applyIf(reader, {
18783                     model: model,
18784                     type : me.defaultReaderType
18785                 });
18786             }
18787             me.reader = Ext.createByAlias('reader.' + reader.type, reader);
18788         }
18789         return me.reader || null;
18790     }
18791 });
18792
18793
18794 Ext.define('Ext.ModelManager', {
18795     extend: 'Ext.AbstractManager',
18796     alternateClassName: 'Ext.ModelMgr',
18797     requires: ['Ext.data.Association'],
18798
18799     singleton: true,
18800
18801     typeName: 'mtype',
18802
18803     
18804     associationStack: [],
18805
18806     
18807     registerType: function(name, config) {
18808         var proto = config.prototype,
18809             model;
18810         if (proto && proto.isModel) {
18811             
18812             model = config;
18813         } else {
18814             
18815             if (!config.extend) {
18816                 config.extend = 'Ext.data.Model';
18817             }
18818             model = Ext.define(name, config);
18819         }
18820         this.types[name] = model;
18821         return model;
18822     },
18823
18824     
18825     onModelDefined: function(model) {
18826         var stack  = this.associationStack,
18827             length = stack.length,
18828             create = [],
18829             association, i, created;
18830
18831         for (i = 0; i < length; i++) {
18832             association = stack[i];
18833
18834             if (association.associatedModel == model.modelName) {
18835                 create.push(association);
18836             }
18837         }
18838
18839         for (i = 0, length = create.length; i < length; i++) {
18840             created = create[i];
18841             this.types[created.ownerModel].prototype.associations.add(Ext.data.Association.create(created));
18842             Ext.Array.remove(stack, created);
18843         }
18844     },
18845
18846     
18847     registerDeferredAssociation: function(association){
18848         this.associationStack.push(association);
18849     },
18850
18851     
18852     getModel: function(id) {
18853         var model = id;
18854         if (typeof model == 'string') {
18855             model = this.types[model];
18856         }
18857         return model;
18858     },
18859
18860     
18861     create: function(config, name, id) {
18862         var con = typeof name == 'function' ? name : this.types[name || config.name];
18863
18864         return new con(config, id);
18865     }
18866 }, function() {
18867
18868     
18869     Ext.regModel = function() {
18870         return this.ModelManager.registerType.apply(this.ModelManager, arguments);
18871     };
18872 });
18873
18874
18875 Ext.define('Ext.PluginManager', {
18876     extend: 'Ext.AbstractManager',
18877     alternateClassName: 'Ext.PluginMgr',
18878     singleton: true,
18879     typeName: 'ptype',
18880
18881     
18882     
18883     
18884     
18885     
18886     
18887     
18888     
18889     
18890     
18891     
18892     
18893     
18894     
18895     
18896     
18897     
18898     
18899
18900     create : function(config, defaultType){
18901         if (config.init) {
18902             return config;
18903         } else {
18904             return Ext.createByAlias('plugin.' + (config.ptype || defaultType), config);
18905         }
18906
18907         
18908         
18909         
18910         
18911         
18912         
18913         
18914     },
18915
18916     
18917     findByType: function(type, defaultsOnly) {
18918         var matches = [],
18919             types   = this.types;
18920
18921         for (var name in types) {
18922             if (!types.hasOwnProperty(name)) {
18923                 continue;
18924             }
18925             var item = types[name];
18926
18927             if (item.type == type && (!defaultsOnly || (defaultsOnly === true && item.isDefault))) {
18928                 matches.push(item);
18929             }
18930         }
18931
18932         return matches;
18933     }
18934 }, function() {
18935     
18936     Ext.preg = function() {
18937         return Ext.PluginManager.registerType.apply(Ext.PluginManager, arguments);
18938     };
18939 });
18940
18941
18942 Ext.define('Ext.Template', {
18943
18944     
18945
18946     requires: ['Ext.DomHelper', 'Ext.util.Format'],
18947
18948     inheritableStatics: {
18949         
18950         from: function(el, config) {
18951             el = Ext.getDom(el);
18952             return new this(el.value || el.innerHTML, config || '');
18953         }
18954     },
18955
18956     
18957
18958     
18959     constructor: function(html) {
18960         var me = this,
18961             args = arguments,
18962             buffer = [],
18963             i = 0,
18964             length = args.length,
18965             value;
18966
18967         me.initialConfig = {};
18968
18969         if (length > 1) {
18970             for (; i < length; i++) {
18971                 value = args[i];
18972                 if (typeof value == 'object') {
18973                     Ext.apply(me.initialConfig, value);
18974                     Ext.apply(me, value);
18975                 } else {
18976                     buffer.push(value);
18977                 }
18978             }
18979             html = buffer.join('');
18980         } else {
18981             if (Ext.isArray(html)) {
18982                 buffer.push(html.join(''));
18983             } else {
18984                 buffer.push(html);
18985             }
18986         }
18987
18988         
18989         me.html = buffer.join('');
18990
18991         if (me.compiled) {
18992             me.compile();
18993         }
18994     },
18995
18996     isTemplate: true,
18997
18998     
18999
19000     
19001     disableFormats: false,
19002
19003     re: /\{([\w\-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
19004
19005     
19006     applyTemplate: function(values) {
19007         var me = this,
19008             useFormat = me.disableFormats !== true,
19009             fm = Ext.util.Format,
19010             tpl = me;
19011
19012         if (me.compiled) {
19013             return me.compiled(values);
19014         }
19015         function fn(m, name, format, args) {
19016             if (format && useFormat) {
19017                 if (args) {
19018                     args = [values[name]].concat(Ext.functionFactory('return ['+ args +'];')());
19019                 } else {
19020                     args = [values[name]];
19021                 }
19022                 if (format.substr(0, 5) == "this.") {
19023                     return tpl[format.substr(5)].apply(tpl, args);
19024                 }
19025                 else {
19026                     return fm[format].apply(fm, args);
19027                 }
19028             }
19029             else {
19030                 return values[name] !== undefined ? values[name] : "";
19031             }
19032         }
19033         return me.html.replace(me.re, fn);
19034     },
19035
19036     
19037     set: function(html, compile) {
19038         var me = this;
19039         me.html = html;
19040         me.compiled = null;
19041         return compile ? me.compile() : me;
19042     },
19043
19044     compileARe: /\\/g,
19045     compileBRe: /(\r\n|\n)/g,
19046     compileCRe: /'/g,
19047
19048     /**
19049      * Compiles the template into an internal function, eliminating the RegEx overhead.
19050      * @return {Ext.Template} this
19051      */
19052     compile: function() {
19053         var me = this,
19054             fm = Ext.util.Format,
19055             useFormat = me.disableFormats !== true,
19056             body, bodyReturn;
19057
19058         function fn(m, name, format, args) {
19059             if (format && useFormat) {
19060                 args = args ? ',' + args: "";
19061                 if (format.substr(0, 5) != "this.") {
19062                     format = "fm." + format + '(';
19063                 }
19064                 else {
19065                     format = 'this.' + format.substr(5) + '(';
19066                 }
19067             }
19068             else {
19069                 args = '';
19070                 format = "(values['" + name + "'] == undefined ? '' : ";
19071             }
19072             return "'," + format + "values['" + name + "']" + args + ") ,'";
19073         }
19074
19075         bodyReturn = me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn);
19076         body = "this.compiled = function(values){ return ['" + bodyReturn + "'].join('');};";
19077         eval(body);
19078         return me;
19079     },
19080
19081     /**
19082      * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
19083      *
19084      * @param {String/HTMLElement/Ext.Element} el The context element
19085      * @param {Object/Array} values The template values. See {@link #applyTemplate} for details.
19086      * @param {Boolean} returnElement (optional) true to return a Ext.Element.
19087      * @return {HTMLElement/Ext.Element} The new node or Element
19088      */
19089     insertFirst: function(el, values, returnElement) {
19090         return this.doInsert('afterBegin', el, values, returnElement);
19091     },
19092
19093     /**
19094      * Applies the supplied values to the template and inserts the new node(s) before el.
19095      *
19096      * @param {String/HTMLElement/Ext.Element} el The context element
19097      * @param {Object/Array} values The template values. See {@link #applyTemplate} for details.
19098      * @param {Boolean} returnElement (optional) true to return a Ext.Element.
19099      * @return {HTMLElement/Ext.Element} The new node or Element
19100      */
19101     insertBefore: function(el, values, returnElement) {
19102         return this.doInsert('beforeBegin', el, values, returnElement);
19103     },
19104
19105     /**
19106      * Applies the supplied values to the template and inserts the new node(s) after el.
19107      *
19108      * @param {String/HTMLElement/Ext.Element} el The context element
19109      * @param {Object/Array} values The template values. See {@link #applyTemplate} for details.
19110      * @param {Boolean} returnElement (optional) true to return a Ext.Element.
19111      * @return {HTMLElement/Ext.Element} The new node or Element
19112      */
19113     insertAfter: function(el, values, returnElement) {
19114         return this.doInsert('afterEnd', el, values, returnElement);
19115     },
19116
19117     /**
19118      * Applies the supplied `values` to the template and appends the new node(s) to the specified `el`.
19119      *
19120      * For example usage see {@link Ext.Template Ext.Template class docs}.
19121      *
19122      * @param {String/HTMLElement/Ext.Element} el The context element
19123      * @param {Object/Array} values The template values. See {@link #applyTemplate} for details.
19124      * @param {Boolean} returnElement (optional) true to return an Ext.Element.
19125      * @return {HTMLElement/Ext.Element} The new node or Element
19126      */
19127     append: function(el, values, returnElement) {
19128         return this.doInsert('beforeEnd', el, values, returnElement);
19129     },
19130
19131     doInsert: function(where, el, values, returnEl) {
19132         el = Ext.getDom(el);
19133         var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
19134         return returnEl ? Ext.get(newNode, true) : newNode;
19135     },
19136
19137     /**
19138      * Applies the supplied values to the template and overwrites the content of el with the new node(s).
19139      *
19140      * @param {String/HTMLElement/Ext.Element} el The context element
19141      * @param {Object/Array} values The template values. See {@link #applyTemplate} for details.
19142      * @param {Boolean} returnElement (optional) true to return a Ext.Element.
19143      * @return {HTMLElement/Ext.Element} The new node or Element
19144      */
19145     overwrite: function(el, values, returnElement) {
19146         el = Ext.getDom(el);
19147         el.innerHTML = this.applyTemplate(values);
19148         return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
19149     }
19150 }, function() {
19151
19152     /**
19153      * @method apply
19154      * @member Ext.Template
19155      * Alias for {@link #applyTemplate}.
19156      * @alias Ext.Template#applyTemplate
19157      */
19158     this.createAlias('apply', 'applyTemplate');
19159 });
19160
19161 /**
19162  * A template class that supports advanced functionality like:
19163  *
19164  * - Autofilling arrays using templates and sub-templates
19165  * - Conditional processing with basic comparison operators
19166  * - Basic math function support
19167  * - Execute arbitrary inline code with special built-in template variables
19168  * - Custom member functions
19169  * - Many special tags and built-in operators that aren't defined as part of the API, but are supported in the templates that can be created
19170  *
19171  * XTemplate provides the templating mechanism built into:
19172  *
19173  * - {@link Ext.view.View}
19174  *
19175  * The {@link Ext.Template} describes the acceptable parameters to pass to the constructor. The following examples
19176  * demonstrate all of the supported features.
19177  *
19178  * # Sample Data
19179  *
19180  * This is the data object used for reference in each code example:
19181  *
19182  *     var data = {
19183  *         name: 'Tommy Maintz',
19184  *         title: 'Lead Developer',
19185  *         company: 'Sencha Inc.',
19186  *         email: 'tommy@sencha.com',
19187  *         address: '5 Cups Drive',
19188  *         city: 'Palo Alto',
19189  *         state: 'CA',
19190  *         zip: '44102',
19191  *         drinks: ['Coffee', 'Soda', 'Water'],
19192  *         kids: [
19193  *             {
19194  *                 name: 'Joshua',
19195  *                 age:3
19196  *             },
19197  *             {
19198  *                 name: 'Matthew',
19199  *                 age:2
19200  *             },
19201  *             {
19202  *                 name: 'Solomon',
19203  *                 age:0
19204  *             }
19205  *         ]
19206  *     };
19207  *
19208  * # Auto filling of arrays
19209  *
19210  * The **tpl** tag and the **for** operator are used to process the provided data object:
19211  *
19212  * - If the value specified in for is an array, it will auto-fill, repeating the template block inside the tpl
19213  *   tag for each item in the array.
19214  * - If for="." is specified, the data object provided is examined.
19215  * - While processing an array, the special variable {#} will provide the current array index + 1 (starts at 1, not 0).
19216  *
19217  * Examples:
19218  *
19219  *     <tpl for=".">...</tpl>       // loop through array at root node
19220  *     <tpl for="foo">...</tpl>     // loop through array at foo node
19221  *     <tpl for="foo.bar">...</tpl> // loop through array at foo.bar node
19222  *
19223  * Using the sample data above:
19224  *
19225  *     var tpl = new Ext.XTemplate(
19226  *         '<p>Kids: ',
19227  *         '<tpl for=".">',       // process the data.kids node
19228  *             '<p>{#}. {name}</p>',  // use current array index to autonumber
19229  *         '</tpl></p>'
19230  *     );
19231  *     tpl.overwrite(panel.body, data.kids); // pass the kids property of the data object
19232  *
19233  * An example illustrating how the **for** property can be leveraged to access specified members of the provided data
19234  * object to populate the template:
19235  *
19236  *     var tpl = new Ext.XTemplate(
19237  *         '<p>Name: {name}</p>',
19238  *         '<p>Title: {title}</p>',
19239  *         '<p>Company: {company}</p>',
19240  *         '<p>Kids: ',
19241  *         '<tpl for="kids">',     // interrogate the kids property within the data
19242  *             '<p>{name}</p>',
19243  *         '</tpl></p>'
19244  *     );
19245  *     tpl.overwrite(panel.body, data);  // pass the root node of the data object
19246  *
19247  * Flat arrays that contain values (and not objects) can be auto-rendered using the special **`{.}`** variable inside a
19248  * loop. This variable will represent the value of the array at the current index:
19249  *
19250  *     var tpl = new Ext.XTemplate(
19251  *         '<p>{name}\'s favorite beverages:</p>',
19252  *         '<tpl for="drinks">',
19253  *             '<div> - {.}</div>',
19254  *         '</tpl>'
19255  *     );
19256  *     tpl.overwrite(panel.body, data);
19257  *
19258  * When processing a sub-template, for example while looping through a child array, you can access the parent object's
19259  * members via the **parent** object:
19260  *
19261  *     var tpl = new Ext.XTemplate(
19262  *         '<p>Name: {name}</p>',
19263  *         '<p>Kids: ',
19264  *         '<tpl for="kids">',
19265  *             '<tpl if="age &gt; 1">',
19266  *                 '<p>{name}</p>',
19267  *                 '<p>Dad: {parent.name}</p>',
19268  *             '</tpl>',
19269  *         '</tpl></p>'
19270  *     );
19271  *     tpl.overwrite(panel.body, data);
19272  *
19273  * # Conditional processing with basic comparison operators
19274  *
19275  * The **tpl** tag and the **if** operator are used to provide conditional checks for deciding whether or not to render
19276  * specific parts of the template. Notes:
19277  *
19278  * - Double quotes must be encoded if used within the conditional
19279  * - There is no else operator -- if needed, two opposite if statements should be used.
19280  *
19281  * Examples:
19282  *
19283  *     <tpl if="age > 1 && age < 10">Child</tpl>
19284  *     <tpl if="age >= 10 && age < 18">Teenager</tpl>
19285  *     <tpl if="this.isGirl(name)">...</tpl>
19286  *     <tpl if="id==\'download\'">...</tpl>
19287  *     <tpl if="needsIcon"><img src="{icon}" class="{iconCls}"/></tpl>
19288  *     // no good:
19289  *     <tpl if="name == "Tommy"">Hello</tpl>
19290  *     // encode " if it is part of the condition, e.g.
19291  *     <tpl if="name == &quot;Tommy&quot;">Hello</tpl>
19292  *
19293  * Using the sample data above:
19294  *
19295  *     var tpl = new Ext.XTemplate(
19296  *         '<p>Name: {name}</p>',
19297  *         '<p>Kids: ',
19298  *         '<tpl for="kids">',
19299  *             '<tpl if="age &gt; 1">',
19300  *                 '<p>{name}</p>',
19301  *             '</tpl>',
19302  *         '</tpl></p>'
19303  *     );
19304  *     tpl.overwrite(panel.body, data);
19305  *
19306  * # Basic math support
19307  *
19308  * The following basic math operators may be applied directly on numeric data values:
19309  *
19310  *     + - * /
19311  *
19312  * For example:
19313  *
19314  *     var tpl = new Ext.XTemplate(
19315  *         '<p>Name: {name}</p>',
19316  *         '<p>Kids: ',
19317  *         '<tpl for="kids">',
19318  *             '<tpl if="age &gt; 1">',  // <-- Note that the > is encoded
19319  *                 '<p>{#}: {name}</p>',  // <-- Auto-number each item
19320  *                 '<p>In 5 Years: {age+5}</p>',  // <-- Basic math
19321  *                 '<p>Dad: {parent.name}</p>',
19322  *             '</tpl>',
19323  *         '</tpl></p>'
19324  *     );
19325  *     tpl.overwrite(panel.body, data);
19326  *
19327  * # Execute arbitrary inline code with special built-in template variables
19328  *
19329  * Anything between `{[ ... ]}` is considered code to be executed in the scope of the template. There are some special
19330  * variables available in that code:
19331  *
19332  * - **values**: The values in the current scope. If you are using scope changing sub-templates,
19333  *   you can change what values is.
19334  * - **parent**: The scope (values) of the ancestor template.
19335  * - **xindex**: If you are in a looping template, the index of the loop you are in (1-based).
19336  * - **xcount**: If you are in a looping template, the total length of the array you are looping.
19337  *
19338  * This example demonstrates basic row striping using an inline code block and the xindex variable:
19339  *
19340  *     var tpl = new Ext.XTemplate(
19341  *         '<p>Name: {name}</p>',
19342  *         '<p>Company: {[values.company.toUpperCase() + ", " + values.title]}</p>',
19343  *         '<p>Kids: ',
19344  *         '<tpl for="kids">',
19345  *             '<div class="{[xindex % 2 === 0 ? "even" : "odd"]}">',
19346  *             '{name}',
19347  *             '</div>',
19348  *         '</tpl></p>'
19349  *      );
19350  *     tpl.overwrite(panel.body, data);
19351  *
19352  * # Template member functions
19353  *
19354  * One or more member functions can be specified in a configuration object passed into the XTemplate constructor for
19355  * more complex processing:
19356  *
19357  *     var tpl = new Ext.XTemplate(
19358  *         '<p>Name: {name}</p>',
19359  *         '<p>Kids: ',
19360  *         '<tpl for="kids">',
19361  *             '<tpl if="this.isGirl(name)">',
19362  *                 '<p>Girl: {name} - {age}</p>',
19363  *             '</tpl>',
19364  *              // use opposite if statement to simulate 'else' processing:
19365  *             '<tpl if="this.isGirl(name) == false">',
19366  *                 '<p>Boy: {name} - {age}</p>',
19367  *             '</tpl>',
19368  *             '<tpl if="this.isBaby(age)">',
19369  *                 '<p>{name} is a baby!</p>',
19370  *             '</tpl>',
19371  *         '</tpl></p>',
19372  *         {
19373  *             // XTemplate configuration:
19374  *             disableFormats: true,
19375  *             // member functions:
19376  *             isGirl: function(name){
19377  *                return name == 'Sara Grace';
19378  *             },
19379  *             isBaby: function(age){
19380  *                return age < 1;
19381  *             }
19382  *         }
19383  *     );
19384  *     tpl.overwrite(panel.body, data);
19385  */
19386 Ext.define('Ext.XTemplate', {
19387
19388     /* Begin Definitions */
19389
19390     extend: 'Ext.Template',
19391
19392     /* End Definitions */
19393
19394     argsRe: /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/,
19395     nameRe: /^<tpl\b[^>]*?for="(.*?)"/,
19396     ifRe: /^<tpl\b[^>]*?if="(.*?)"/,
19397     execRe: /^<tpl\b[^>]*?exec="(.*?)"/,
19398     constructor: function() {
19399         this.callParent(arguments);
19400
19401         var me = this,
19402             html = me.html,
19403             argsRe = me.argsRe,
19404             nameRe = me.nameRe,
19405             ifRe = me.ifRe,
19406             execRe = me.execRe,
19407             id = 0,
19408             tpls = [],
19409             VALUES = 'values',
19410             PARENT = 'parent',
19411             XINDEX = 'xindex',
19412             XCOUNT = 'xcount',
19413             RETURN = 'return ',
19414             WITHVALUES = 'with(values){ ',
19415             m, matchName, matchIf, matchExec, exp, fn, exec, name, i;
19416
19417         html = ['<tpl>', html, '</tpl>'].join('');
19418
19419         while ((m = html.match(argsRe))) {
19420             exp = null;
19421             fn = null;
19422             exec = null;
19423             matchName = m[0].match(nameRe);
19424             matchIf = m[0].match(ifRe);
19425             matchExec = m[0].match(execRe);
19426
19427             exp = matchIf ? matchIf[1] : null;
19428             if (exp) {
19429                 fn = Ext.functionFactory(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + 'try{' + RETURN + Ext.String.htmlDecode(exp) + ';}catch(e){return;}}');
19430             }
19431
19432             exp = matchExec ? matchExec[1] : null;
19433             if (exp) {
19434                 exec = Ext.functionFactory(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + Ext.String.htmlDecode(exp) + ';}');
19435             }
19436
19437             name = matchName ? matchName[1] : null;
19438             if (name) {
19439                 if (name === '.') {
19440                     name = VALUES;
19441                 } else if (name === '..') {
19442                     name = PARENT;
19443                 }
19444                 name = Ext.functionFactory(VALUES, PARENT, 'try{' + WITHVALUES + RETURN + name + ';}}catch(e){return;}');
19445             }
19446
19447             tpls.push({
19448                 id: id,
19449                 target: name,
19450                 exec: exec,
19451                 test: fn,
19452                 body: m[1] || ''
19453             });
19454
19455             html = html.replace(m[0], '{xtpl' + id + '}');
19456             id = id + 1;
19457         }
19458
19459         for (i = tpls.length - 1; i >= 0; --i) {
19460             me.compileTpl(tpls[i]);
19461         }
19462         me.master = tpls[tpls.length - 1];
19463         me.tpls = tpls;
19464     },
19465
19466     // @private
19467     applySubTemplate: function(id, values, parent, xindex, xcount) {
19468         var me = this, t = me.tpls[id];
19469         return t.compiled.call(me, values, parent, xindex, xcount);
19470     },
19471
19472     /**
19473      * @cfg {RegExp} codeRe
19474      * The regular expression used to match code variables. Default: matches {[expression]}.
19475      */
19476     codeRe: /\{\[((?:\\\]|.|\n)*?)\]\}/g,
19477
19478     /**
19479      * @cfg {Boolean} compiled
19480      * Only applies to {@link Ext.Template}, XTemplates are compiled automatically.
19481      */
19482
19483     re: /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\/]\s?[\d\.\+\-\*\/\(\)]+)?\}/g,
19484
19485     // @private
19486     compileTpl: function(tpl) {
19487         var fm = Ext.util.Format,
19488             me = this,
19489             useFormat = me.disableFormats !== true,
19490             body, bodyReturn, evaluatedFn;
19491
19492         function fn(m, name, format, args, math) {
19493             var v;
19494             // name is what is inside the {}
19495             // Name begins with xtpl, use a Sub Template
19496             if (name.substr(0, 4) == 'xtpl') {
19497                 return "',this.applySubTemplate(" + name.substr(4) + ", values, parent, xindex, xcount),'";
19498             }
19499             // name = "." - Just use the values object.
19500             if (name == '.') {
19501                 // filter to not include arrays/objects/nulls
19502                 v = 'Ext.Array.indexOf(["string", "number", "boolean"], typeof values) > -1 || Ext.isDate(values) ? values : ""';
19503             }
19504
19505             // name = "#" - Use the xindex
19506             else if (name == '#') {
19507                 v = 'xindex';
19508             }
19509             else if (name.substr(0, 7) == "parent.") {
19510                 v = name;
19511             }
19512             // name has a . in it - Use object literal notation, starting from values
19513             else if (name.indexOf('.') != -1) {
19514                 v = "values." + name;
19515             }
19516
19517             // name is a property of values
19518             else {
19519                 v = "values['" + name + "']";
19520             }
19521             if (math) {
19522                 v = '(' + v + math + ')';
19523             }
19524             if (format && useFormat) {
19525                 args = args ? ',' + args : "";
19526                 if (format.substr(0, 5) != "this.") {
19527                     format = "fm." + format + '(';
19528                 }
19529                 else {
19530                     format = 'this.' + format.substr(5) + '(';
19531                 }
19532             }
19533             else {
19534                 args = '';
19535                 format = "(" + v + " === undefined ? '' : ";
19536             }
19537             return "'," + format + v + args + "),'";
19538         }
19539
19540         function codeFn(m, code) {
19541             // Single quotes get escaped when the template is compiled, however we want to undo this when running code.
19542             return "',(" + code.replace(me.compileARe, "'") + "),'";
19543         }
19544
19545         bodyReturn = tpl.body.replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn).replace(me.codeRe, codeFn);
19546         body = "evaluatedFn = function(values, parent, xindex, xcount){return ['" + bodyReturn + "'].join('');};";
19547         eval(body);
19548
19549         tpl.compiled = function(values, parent, xindex, xcount) {
19550             var vs,
19551                 length,
19552                 buffer,
19553                 i;
19554
19555             if (tpl.test && !tpl.test.call(me, values, parent, xindex, xcount)) {
19556                 return '';
19557             }
19558
19559             vs = tpl.target ? tpl.target.call(me, values, parent) : values;
19560             if (!vs) {
19561                return '';
19562             }
19563
19564             parent = tpl.target ? values : parent;
19565             if (tpl.target && Ext.isArray(vs)) {
19566                 buffer = [];
19567                 length = vs.length;
19568                 if (tpl.exec) {
19569                     for (i = 0; i < length; i++) {
19570                         buffer[buffer.length] = evaluatedFn.call(me, vs[i], parent, i + 1, length);
19571                         tpl.exec.call(me, vs[i], parent, i + 1, length);
19572                     }
19573                 } else {
19574                     for (i = 0; i < length; i++) {
19575                         buffer[buffer.length] = evaluatedFn.call(me, vs[i], parent, i + 1, length);
19576                     }
19577                 }
19578                 return buffer.join('');
19579             }
19580
19581             if (tpl.exec) {
19582                 tpl.exec.call(me, vs, parent, xindex, xcount);
19583             }
19584             return evaluatedFn.call(me, vs, parent, xindex, xcount);
19585         };
19586
19587         return this;
19588     },
19589
19590     // inherit docs from Ext.Template
19591     applyTemplate: function(values) {
19592         return this.master.compiled.call(this, values, {}, 1, 1);
19593     },
19594
19595     /**
19596      * Does nothing. XTemplates are compiled automatically, so this function simply returns this.
19597      * @return {Ext.XTemplate} this
19598      */
19599     compile: function() {
19600         return this;
19601     }
19602 }, function() {
19603     // re-create the alias, inheriting it from Ext.Template doesn't work as intended.
19604     this.createAlias('apply', 'applyTemplate');
19605 });
19606
19607
19608 Ext.define('Ext.app.Controller', {
19609
19610     mixins: {
19611         observable: 'Ext.util.Observable'
19612     },
19613
19614     
19615     
19616     
19617
19618     
19619
19620     
19621
19622     onClassExtended: function(cls, data) {
19623         var className = Ext.getClassName(cls),
19624             match = className.match(/^(.*)\.controller\./);
19625
19626         if (match !== null) {
19627             var namespace = Ext.Loader.getPrefix(className) || match[1],
19628                 onBeforeClassCreated = data.onBeforeClassCreated,
19629                 requires = [],
19630                 modules = ['model', 'view', 'store'],
19631                 prefix;
19632
19633             data.onBeforeClassCreated = function(cls, data) {
19634                 var i, ln, module,
19635                     items, j, subLn, item;
19636
19637                 for (i = 0,ln = modules.length; i < ln; i++) {
19638                     module = modules[i];
19639
19640                     items = Ext.Array.from(data[module + 's']);
19641
19642                     for (j = 0,subLn = items.length; j < subLn; j++) {
19643                         item = items[j];
19644
19645                         prefix = Ext.Loader.getPrefix(item);
19646
19647                         if (prefix === '' || prefix === item) {
19648                             requires.push(namespace + '.' + module + '.' + item);
19649                         }
19650                         else {
19651                             requires.push(item);
19652                         }
19653                     }
19654                 }
19655
19656                 Ext.require(requires, Ext.Function.pass(onBeforeClassCreated, arguments, this));
19657             };
19658         }
19659     },
19660
19661     
19662     constructor: function(config) {
19663         this.mixins.observable.constructor.call(this, config);
19664
19665         Ext.apply(this, config || {});
19666
19667         this.createGetters('model', this.models);
19668         this.createGetters('store', this.stores);
19669         this.createGetters('view', this.views);
19670
19671         if (this.refs) {
19672             this.ref(this.refs);
19673         }
19674     },
19675
19676     
19677     init: function(application) {},
19678
19679     
19680     onLaunch: function(application) {},
19681
19682     createGetters: function(type, refs) {
19683         type = Ext.String.capitalize(type);
19684         Ext.Array.each(refs, function(ref) {
19685             var fn = 'get',
19686                 parts = ref.split('.');
19687
19688             
19689             Ext.Array.each(parts, function(part) {
19690                 fn += Ext.String.capitalize(part);
19691             });
19692             fn += type;
19693
19694             if (!this[fn]) {
19695                 this[fn] = Ext.Function.pass(this['get' + type], [ref], this);
19696             }
19697             
19698             this[fn](ref);
19699         },
19700         this);
19701     },
19702
19703     ref: function(refs) {
19704         var me = this;
19705         refs = Ext.Array.from(refs);
19706         Ext.Array.each(refs, function(info) {
19707             var ref = info.ref,
19708                 fn = 'get' + Ext.String.capitalize(ref);
19709             if (!me[fn]) {
19710                 me[fn] = Ext.Function.pass(me.getRef, [ref, info], me);
19711             }
19712         });
19713     },
19714
19715     getRef: function(ref, info, config) {
19716         this.refCache = this.refCache || {};
19717         info = info || {};
19718         config = config || {};
19719
19720         Ext.apply(info, config);
19721
19722         if (info.forceCreate) {
19723             return Ext.ComponentManager.create(info, 'component');
19724         }
19725
19726         var me = this,
19727             selector = info.selector,
19728             cached = me.refCache[ref];
19729
19730         if (!cached) {
19731             me.refCache[ref] = cached = Ext.ComponentQuery.query(info.selector)[0];
19732             if (!cached && info.autoCreate) {
19733                 me.refCache[ref] = cached = Ext.ComponentManager.create(info, 'component');
19734             }
19735             if (cached) {
19736                 cached.on('beforedestroy', function() {
19737                     me.refCache[ref] = null;
19738                 });
19739             }
19740         }
19741
19742         return cached;
19743     },
19744
19745     
19746     control: function(selectors, listeners) {
19747         this.application.control(selectors, listeners, this);
19748     },
19749
19750     
19751     getController: function(name) {
19752         return this.application.getController(name);
19753     },
19754
19755     
19756     getStore: function(name) {
19757         return this.application.getStore(name);
19758     },
19759
19760     
19761     getModel: function(model) {
19762         return this.application.getModel(model);
19763     },
19764
19765     
19766     getView: function(view) {
19767         return this.application.getView(view);
19768     }
19769 });
19770
19771
19772 Ext.define('Ext.data.IdGenerator', {
19773
19774     isGenerator: true,
19775
19776     
19777     constructor: function(config) {
19778         var me = this;
19779
19780         Ext.apply(me, config);
19781
19782         if (me.id) {
19783             Ext.data.IdGenerator.all[me.id] = me;
19784         }
19785     },
19786
19787     
19788
19789     getRecId: function (rec) {
19790         return rec.modelName + '-' + rec.internalId;
19791     },
19792
19793     
19794
19795     statics: {
19796         
19797         all: {},
19798
19799         
19800         get: function (config) {
19801             var generator,
19802                 id,
19803                 type;
19804
19805             if (typeof config == 'string') {
19806                 id = type = config;
19807                 config = null;
19808             } else if (config.isGenerator) {
19809                 return config;
19810             } else {
19811                 id = config.id || config.type;
19812                 type = config.type;
19813             }
19814
19815             generator = this.all[id];
19816             if (!generator) {
19817                 generator = Ext.create('idgen.' + type, config);
19818             }
19819
19820             return generator;
19821         }
19822     }
19823 });
19824
19825
19826 Ext.define('Ext.data.SortTypes', {
19827     
19828     singleton: true,
19829     
19830     
19831     none : function(s) {
19832         return s;
19833     },
19834
19835     
19836     stripTagsRE : /<\/?[^>]+>/gi,
19837
19838     
19839     asText : function(s) {
19840         return String(s).replace(this.stripTagsRE, "");
19841     },
19842
19843     
19844     asUCText : function(s) {
19845         return String(s).toUpperCase().replace(this.stripTagsRE, "");
19846     },
19847
19848     
19849     asUCString : function(s) {
19850         return String(s).toUpperCase();
19851     },
19852
19853     
19854     asDate : function(s) {
19855         if(!s){
19856             return 0;
19857         }
19858         if(Ext.isDate(s)){
19859             return s.getTime();
19860         }
19861         return Date.parse(String(s));
19862     },
19863
19864     
19865     asFloat : function(s) {
19866         var val = parseFloat(String(s).replace(/,/g, ""));
19867         return isNaN(val) ? 0 : val;
19868     },
19869
19870     
19871     asInt : function(s) {
19872         var val = parseInt(String(s).replace(/,/g, ""), 10);
19873         return isNaN(val) ? 0 : val;
19874     }
19875 });
19876
19877 Ext.define('Ext.util.Filter', {
19878
19879     
19880
19881     
19882     
19883     
19884     
19885     
19886     
19887     anyMatch: false,
19888     
19889     
19890     exactMatch: false,
19891     
19892     
19893     caseSensitive: false,
19894     
19895     
19896
19897     
19898     constructor: function(config) {
19899         var me = this;
19900         Ext.apply(me, config);
19901         
19902         
19903         
19904         me.filter = me.filter || me.filterFn;
19905         
19906         if (me.filter === undefined) {
19907             if (me.property === undefined || me.value === undefined) {
19908                 
19909                 
19910                 
19911                 
19912             } else {
19913                 me.filter = me.createFilterFn();
19914             }
19915             
19916             me.filterFn = me.filter;
19917         }
19918     },
19919     
19920     
19921     createFilterFn: function() {
19922         var me       = this,
19923             matcher  = me.createValueMatcher(),
19924             property = me.property;
19925         
19926         return function(item) {
19927             var value = me.getRoot.call(me, item)[property];
19928             return matcher === null ? value === null : matcher.test(value);
19929         };
19930     },
19931     
19932     
19933     getRoot: function(item) {
19934         var root = this.root;
19935         return root === undefined ? item : item[root];
19936     },
19937     
19938     
19939     createValueMatcher : function() {
19940         var me            = this,
19941             value         = me.value,
19942             anyMatch      = me.anyMatch,
19943             exactMatch    = me.exactMatch,
19944             caseSensitive = me.caseSensitive,
19945             escapeRe      = Ext.String.escapeRegex;
19946             
19947         if (value === null) {
19948             return value;
19949         }
19950         
19951         if (!value.exec) { 
19952             value = String(value);
19953
19954             if (anyMatch === true) {
19955                 value = escapeRe(value);
19956             } else {
19957                 value = '^' + escapeRe(value);
19958                 if (exactMatch === true) {
19959                     value += '$';
19960                 }
19961             }
19962             value = new RegExp(value, caseSensitive ? '' : 'i');
19963          }
19964          
19965          return value;
19966     }
19967 });
19968
19969 Ext.define('Ext.util.Sorter', {
19970
19971     
19972     
19973     
19974     
19975     
19976     
19977     
19978     
19979     
19980     direction: "ASC",
19981     
19982     constructor: function(config) {
19983         var me = this;
19984         
19985         Ext.apply(me, config);
19986         
19987         
19988         me.updateSortFunction();
19989     },
19990     
19991     
19992     createSortFunction: function(sorterFn) {
19993         var me        = this,
19994             property  = me.property,
19995             direction = me.direction || "ASC",
19996             modifier  = direction.toUpperCase() == "DESC" ? -1 : 1;
19997         
19998         
19999         
20000         return function(o1, o2) {
20001             return modifier * sorterFn.call(me, o1, o2);
20002         };
20003     },
20004     
20005     
20006     defaultSorterFn: function(o1, o2) {
20007         var me = this,
20008             transform = me.transform,
20009             v1 = me.getRoot(o1)[me.property],
20010             v2 = me.getRoot(o2)[me.property];
20011             
20012         if (transform) {
20013             v1 = transform(v1);
20014             v2 = transform(v2);
20015         }
20016
20017         return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
20018     },
20019     
20020     
20021     getRoot: function(item) {
20022         return this.root === undefined ? item : item[this.root];
20023     },
20024     
20025     
20026     setDirection: function(direction) {
20027         var me = this;
20028         me.direction = direction;
20029         me.updateSortFunction();
20030     },
20031     
20032     
20033     toggle: function() {
20034         var me = this;
20035         me.direction = Ext.String.toggle(me.direction, "ASC", "DESC");
20036         me.updateSortFunction();
20037     },
20038     
20039     
20040     updateSortFunction: function(fn) {
20041         var me = this;
20042         fn = fn || me.sorterFn || me.defaultSorterFn;
20043         me.sort = me.createSortFunction(fn);
20044     }
20045 });
20046
20047 Ext.define('Ext.data.Operation', {
20048     
20049     synchronous: true,
20050
20051     
20052     action: undefined,
20053
20054     
20055     filters: undefined,
20056
20057     
20058     sorters: undefined,
20059
20060     
20061     group: undefined,
20062
20063     
20064     start: undefined,
20065
20066     
20067     limit: undefined,
20068
20069     
20070     batch: undefined,
20071
20072     
20073     callback: undefined,
20074
20075     
20076     scope: undefined,
20077
20078     
20079     started: false,
20080
20081     
20082     running: false,
20083
20084     
20085     complete: false,
20086
20087     
20088     success: undefined,
20089
20090     
20091     exception: false,
20092
20093     
20094     error: undefined,
20095
20096     
20097     actionCommitRecordsRe: /^(?:create|update)$/i,
20098
20099     
20100     actionSkipSyncRe: /^destroy$/i,
20101
20102     
20103     constructor: function(config) {
20104         Ext.apply(this, config || {});
20105     },
20106
20107     
20108     commitRecords: function (serverRecords) {
20109         var me = this,
20110             mc, index, clientRecords, serverRec, clientRec;
20111
20112         if (!me.actionSkipSyncRe.test(me.action)) {
20113             clientRecords = me.records;
20114
20115             if (clientRecords && clientRecords.length) {
20116                 mc = Ext.create('Ext.util.MixedCollection', true, function(r) {return r.getId();});
20117                 mc.addAll(clientRecords);
20118
20119                 for (index = serverRecords ? serverRecords.length : 0; index--; ) {
20120                     serverRec = serverRecords[index];
20121                     clientRec = mc.get(serverRec.getId());
20122
20123                     if (clientRec) {
20124                         clientRec.beginEdit();
20125                         clientRec.set(serverRec.data);
20126                         clientRec.endEdit(true);
20127                     }
20128                 }
20129
20130                 if (me.actionCommitRecordsRe.test(me.action)) {
20131                     for (index = clientRecords.length; index--; ) {
20132                         clientRecords[index].commit();
20133                     }
20134                 }
20135             }
20136         }
20137     },
20138
20139     
20140     setStarted: function() {
20141         this.started = true;
20142         this.running = true;
20143     },
20144
20145     
20146     setCompleted: function() {
20147         this.complete = true;
20148         this.running  = false;
20149     },
20150
20151     
20152     setSuccessful: function() {
20153         this.success = true;
20154     },
20155
20156     
20157     setException: function(error) {
20158         this.exception = true;
20159         this.success = false;
20160         this.running = false;
20161         this.error = error;
20162     },
20163
20164     
20165     hasException: function() {
20166         return this.exception === true;
20167     },
20168
20169     
20170     getError: function() {
20171         return this.error;
20172     },
20173
20174     
20175     getRecords: function() {
20176         var resultSet = this.getResultSet();
20177
20178         return (resultSet === undefined ? this.records : resultSet.records);
20179     },
20180
20181     
20182     getResultSet: function() {
20183         return this.resultSet;
20184     },
20185
20186     
20187     isStarted: function() {
20188         return this.started === true;
20189     },
20190
20191     
20192     isRunning: function() {
20193         return this.running === true;
20194     },
20195
20196     
20197     isComplete: function() {
20198         return this.complete === true;
20199     },
20200
20201     
20202     wasSuccessful: function() {
20203         return this.isComplete() && this.success === true;
20204     },
20205
20206     
20207     setBatch: function(batch) {
20208         this.batch = batch;
20209     },
20210
20211     
20212     allowWrite: function() {
20213         return this.action != 'read';
20214     }
20215 });
20216
20217 Ext.define('Ext.data.validations', {
20218     singleton: true,
20219     
20220     
20221     presenceMessage: 'must be present',
20222     
20223     
20224     lengthMessage: 'is the wrong length',
20225     
20226     
20227     formatMessage: 'is the wrong format',
20228     
20229     
20230     inclusionMessage: 'is not included in the list of acceptable values',
20231     
20232     
20233     exclusionMessage: 'is not an acceptable value',
20234     
20235     
20236     emailMessage: 'is not a valid email address',
20237     
20238     
20239     emailRe: /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/,
20240     
20241     
20242     presence: function(config, value) {
20243         if (value === undefined) {
20244             value = config;
20245         }
20246         
20247         
20248         return !!value || value === 0;
20249     },
20250     
20251     
20252     length: function(config, value) {
20253         if (value === undefined || value === null) {
20254             return false;
20255         }
20256         
20257         var length = value.length,
20258             min    = config.min,
20259             max    = config.max;
20260         
20261         if ((min && length < min) || (max && length > max)) {
20262             return false;
20263         } else {
20264             return true;
20265         }
20266     },
20267     
20268     
20269     email: function(config, email) {
20270         return Ext.data.validations.emailRe.test(email);
20271     },
20272     
20273     
20274     format: function(config, value) {
20275         return !!(config.matcher && config.matcher.test(value));
20276     },
20277     
20278     
20279     inclusion: function(config, value) {
20280         return config.list && Ext.Array.indexOf(config.list,value) != -1;
20281     },
20282     
20283     
20284     exclusion: function(config, value) {
20285         return config.list && Ext.Array.indexOf(config.list,value) == -1;
20286     }
20287 });
20288
20289 Ext.define('Ext.data.ResultSet', {
20290     
20291     loaded: true,
20292
20293     
20294     count: 0,
20295
20296     
20297     total: 0,
20298
20299     
20300     success: false,
20301
20302     
20303
20304     
20305     constructor: function(config) {
20306         Ext.apply(this, config);
20307
20308         
20309         this.totalRecords = this.total;
20310
20311         if (config.count === undefined) {
20312             this.count = this.records.length;
20313         }
20314     }
20315 });
20316
20317 Ext.define('Ext.data.writer.Writer', {
20318     alias: 'writer.base',
20319     alternateClassName: ['Ext.data.DataWriter', 'Ext.data.Writer'],
20320     
20321     
20322     writeAllFields: true,
20323     
20324     
20325     nameProperty: 'name',
20326
20327     
20328     constructor: function(config) {
20329         Ext.apply(this, config);
20330     },
20331
20332     
20333     write: function(request) {
20334         var operation = request.operation,
20335             records   = operation.records || [],
20336             len       = records.length,
20337             i         = 0,
20338             data      = [];
20339
20340         for (; i < len; i++) {
20341             data.push(this.getRecordData(records[i]));
20342         }
20343         return this.writeRecords(request, data);
20344     },
20345
20346     
20347     getRecordData: function(record) {
20348         var isPhantom = record.phantom === true,
20349             writeAll = this.writeAllFields || isPhantom,
20350             nameProperty = this.nameProperty,
20351             fields = record.fields,
20352             data = {},
20353             changes,
20354             name,
20355             field,
20356             key;
20357         
20358         if (writeAll) {
20359             fields.each(function(field){
20360                 if (field.persist) {
20361                     name = field[nameProperty] || field.name;
20362                     data[name] = record.get(field.name);
20363                 }
20364             });
20365         } else {
20366             
20367             changes = record.getChanges();
20368             for (key in changes) {
20369                 if (changes.hasOwnProperty(key)) {
20370                     field = fields.get(key);
20371                     name = field[nameProperty] || field.name;
20372                     data[name] = changes[key];
20373                 }
20374             }
20375             if (!isPhantom) {
20376                 
20377                 data[record.idProperty] = record.getId();
20378             }
20379         }
20380         return data;
20381     }
20382 });
20383
20384
20385 Ext.define('Ext.util.Floating', {
20386
20387     uses: ['Ext.Layer', 'Ext.window.Window'],
20388
20389     
20390     focusOnToFront: true,
20391
20392     
20393     shadow: 'sides',
20394
20395     constructor: function(config) {
20396         var me = this;
20397         
20398         me.floating = true;
20399         me.el = Ext.create('Ext.Layer', Ext.apply({}, config, {
20400             hideMode: me.hideMode,
20401             hidden: me.hidden,
20402             shadow: Ext.isDefined(me.shadow) ? me.shadow : 'sides',
20403             shadowOffset: me.shadowOffset,
20404             constrain: false,
20405             shim: me.shim === false ? false : undefined
20406         }), me.el);
20407     },
20408
20409     onFloatRender: function() {
20410         var me = this;
20411         me.zIndexParent = me.getZIndexParent();
20412         me.setFloatParent(me.ownerCt);
20413         delete me.ownerCt;
20414
20415         if (me.zIndexParent) {
20416             me.zIndexParent.registerFloatingItem(me);
20417         } else {
20418             Ext.WindowManager.register(me);
20419         }
20420     },
20421
20422     setFloatParent: function(floatParent) {
20423         var me = this;
20424
20425         
20426         if (me.floatParent) {
20427             me.mun(me.floatParent, {
20428                 hide: me.onFloatParentHide,
20429                 show: me.onFloatParentShow,
20430                 scope: me
20431             });
20432         }
20433
20434         me.floatParent = floatParent;
20435
20436         
20437         if (floatParent) {
20438             me.mon(me.floatParent, {
20439                 hide: me.onFloatParentHide,
20440                 show: me.onFloatParentShow,
20441                 scope: me
20442             });
20443         }
20444
20445         
20446         
20447         if ((me.constrain || me.constrainHeader) && !me.constrainTo) {
20448             me.constrainTo = floatParent ? floatParent.getTargetEl() : me.container;
20449         }
20450     },
20451
20452     onFloatParentHide: function() {
20453         var me = this;
20454         
20455         if (me.hideOnParentHide !== false) {
20456             me.showOnParentShow = me.isVisible();
20457             me.hide();
20458         }
20459     },
20460
20461     onFloatParentShow: function() {
20462         if (this.showOnParentShow) {
20463             delete this.showOnParentShow;
20464             this.show();
20465         }
20466     },
20467
20468     
20469     getZIndexParent: function() {
20470         var p = this.ownerCt,
20471             c;
20472
20473         if (p) {
20474             while (p) {
20475                 c = p;
20476                 p = p.ownerCt;
20477             }
20478             if (c.floating) {
20479                 return c;
20480             }
20481         }
20482     },
20483
20484     
20485     
20486     
20487     
20488     
20489     setZIndex: function(index) {
20490         var me = this;
20491         me.el.setZIndex(index);
20492
20493         
20494         index += 10;
20495
20496         
20497         
20498         if (me.floatingItems) {
20499             index = Math.floor(me.floatingItems.setBase(index) / 100) * 100 + 10000;
20500         }
20501         return index;
20502     },
20503
20504     
20505     doConstrain: function(constrainTo) {
20506         var me = this,
20507             vector = me.getConstrainVector(constrainTo || me.el.getScopeParent()),
20508             xy;
20509
20510         if (vector) {
20511             xy = me.getPosition();
20512             xy[0] += vector[0];
20513             xy[1] += vector[1];
20514             me.setPosition(xy);
20515         }
20516     },
20517
20518
20519     
20520     getConstrainVector: function(constrainTo){
20521         var me = this,
20522             el;
20523
20524         if (me.constrain || me.constrainHeader) {
20525             el = me.constrainHeader ? me.header.el : me.el;
20526             constrainTo = constrainTo || (me.floatParent && me.floatParent.getTargetEl()) || me.container;
20527             return el.getConstrainVector(constrainTo);
20528         }
20529     },
20530
20531     
20532     alignTo: function(element, position, offsets) {
20533         if (element.isComponent) {
20534             element = element.getEl();
20535         }
20536         var xy = this.el.getAlignToXY(element, position, offsets);
20537         this.setPagePosition(xy);
20538         return this;
20539     },
20540
20541     
20542     toFront: function(preventFocus) {
20543         var me = this;
20544
20545         
20546         
20547         if (me.zIndexParent) {
20548             me.zIndexParent.toFront(true);
20549         }
20550         if (me.zIndexManager.bringToFront(me)) {
20551             if (!Ext.isDefined(preventFocus)) {
20552                 preventFocus = !me.focusOnToFront;
20553             }
20554             if (!preventFocus) {
20555                 
20556                 
20557                 
20558                 me.focus(false, true);
20559             }
20560         }
20561         return me;
20562     },
20563
20564     
20565     setActive: function(active, newActive) {
20566         var me = this;
20567         
20568         if (active) {
20569             if (me.el.shadow && !me.maximized) {
20570                 me.el.enableShadow(true);
20571             }
20572             me.fireEvent('activate', me);
20573         } else {
20574             
20575             
20576             if ((me instanceof Ext.window.Window) && (newActive instanceof Ext.window.Window)) {
20577                 me.el.disableShadow();
20578             }
20579             me.fireEvent('deactivate', me);
20580         }
20581     },
20582
20583     
20584     toBack: function() {
20585         this.zIndexManager.sendToBack(this);
20586         return this;
20587     },
20588
20589     
20590     center: function() {
20591         var me = this,
20592             xy = me.el.getAlignToXY(me.container, 'c-c');
20593         me.setPagePosition(xy);
20594         return me;
20595     },
20596
20597     
20598     syncShadow : function(){
20599         if (this.floating) {
20600             this.el.sync(true);
20601         }
20602     },
20603
20604     
20605     fitContainer: function() {
20606         var parent = this.floatParent,
20607             container = parent ? parent.getTargetEl() : this.container,
20608             size = container.getViewSize(false);
20609
20610         this.setSize(size);
20611     }
20612 });
20613
20614 Ext.define('Ext.layout.Layout', {
20615
20616     
20617
20618     
20619
20620     isLayout: true,
20621     initialized: false,
20622
20623     statics: {
20624         create: function(layout, defaultType) {
20625             var type;
20626             if (layout instanceof Ext.layout.Layout) {
20627                 return Ext.createByAlias('layout.' + layout);
20628             } else {
20629                 if (!layout || typeof layout === 'string') {
20630                     type = layout || defaultType;
20631                     layout = {};                    
20632                 }
20633                 else {
20634                     type = layout.type || defaultType;
20635                 }
20636                 return Ext.createByAlias('layout.' + type, layout || {});
20637             }
20638         }
20639     },
20640
20641     constructor : function(config) {
20642         this.id = Ext.id(null, this.type + '-');
20643         Ext.apply(this, config);
20644     },
20645
20646     
20647     layout : function() {
20648         var me = this;
20649         me.layoutBusy = true;
20650         me.initLayout();
20651
20652         if (me.beforeLayout.apply(me, arguments) !== false) {
20653             me.layoutCancelled = false;
20654             me.onLayout.apply(me, arguments);
20655             me.childrenChanged = false;
20656             me.owner.needsLayout = false;
20657             me.layoutBusy = false;
20658             me.afterLayout.apply(me, arguments);
20659         }
20660         else {
20661             me.layoutCancelled = true;
20662         }
20663         me.layoutBusy = false;
20664         me.doOwnerCtLayouts();
20665     },
20666
20667     beforeLayout : function() {
20668         this.renderChildren();
20669         return true;
20670     },
20671
20672     renderChildren: function () {
20673         this.renderItems(this.getLayoutItems(), this.getRenderTarget());
20674     },
20675
20676     
20677     renderItems : function(items, target) {
20678         var me = this,
20679             ln = items.length,
20680             i = 0,
20681             item;
20682
20683         for (; i < ln; i++) {
20684             item = items[i];
20685             if (item && !item.rendered) {
20686                 me.renderItem(item, target, i);
20687             } else if (!me.isValidParent(item, target, i)) {
20688                 me.moveItem(item, target, i);
20689             } else {
20690                 
20691                 me.configureItem(item);
20692             }
20693         }
20694     },
20695
20696     
20697     isValidParent : function(item, target, position) {
20698         var dom = item.el ? item.el.dom : Ext.getDom(item);
20699         if (dom && target && target.dom) {
20700             if (Ext.isNumber(position) && dom !== target.dom.childNodes[position]) {
20701                 return false;
20702             }
20703             return (dom.parentNode == (target.dom || target));
20704         }
20705         return false;
20706     },
20707
20708     
20709     renderItem : function(item, target, position) {
20710         var me = this;
20711         if (!item.rendered) {
20712             if (me.itemCls) {
20713                 item.addCls(me.itemCls);
20714             }
20715             if (me.owner.itemCls) {
20716                 item.addCls(me.owner.itemCls);
20717             }
20718             item.render(target, position);
20719             me.configureItem(item);
20720             me.childrenChanged = true;
20721         }
20722     },
20723
20724     
20725     moveItem : function(item, target, position) {
20726         
20727         target = target.dom || target;
20728         if (typeof position == 'number') {
20729             position = target.childNodes[position];
20730         }
20731         target.insertBefore(item.el.dom, position || null);
20732         item.container = Ext.get(target);
20733         this.configureItem(item);
20734         this.childrenChanged = true;
20735     },
20736
20737     
20738     initLayout : function() {
20739         var me = this,
20740             targetCls = me.targetCls;
20741             
20742         if (!me.initialized && !Ext.isEmpty(targetCls)) {
20743             me.getTarget().addCls(targetCls);
20744         }
20745         me.initialized = true;
20746     },
20747
20748     
20749     setOwner : function(owner) {
20750         this.owner = owner;
20751     },
20752
20753     
20754     getLayoutItems : function() {
20755         return [];
20756     },
20757
20758     
20759     configureItem: Ext.emptyFn,
20760     
20761     
20762     onLayout : Ext.emptyFn,
20763     afterLayout : Ext.emptyFn,
20764     onRemove : Ext.emptyFn,
20765     onDestroy : Ext.emptyFn,
20766     doOwnerCtLayouts : Ext.emptyFn,
20767
20768     
20769     afterRemove : function(item) {
20770         var el = item.el,
20771             owner = this.owner,
20772             itemCls = this.itemCls,
20773             ownerCls = owner.itemCls;
20774             
20775         
20776         if (item.rendered && !item.isDestroyed) {
20777             if (itemCls) {
20778                 el.removeCls(itemCls);
20779             }
20780             if (ownerCls) {
20781                 el.removeCls(ownerCls);
20782             }
20783         }
20784
20785         
20786         
20787         
20788         delete item.layoutManagedWidth;
20789         delete item.layoutManagedHeight;
20790     },
20791
20792     
20793     destroy : function() {
20794         var targetCls = this.targetCls,
20795             target;
20796         
20797         if (!Ext.isEmpty(targetCls)) {
20798             target = this.getTarget();
20799             if (target) {
20800                 target.removeCls(targetCls);
20801             }
20802         }
20803         this.onDestroy();
20804     }
20805 });
20806
20807 Ext.define('Ext.ZIndexManager', {
20808
20809     alternateClassName: 'Ext.WindowGroup',
20810
20811     statics: {
20812         zBase : 9000
20813     },
20814
20815     constructor: function(container) {
20816         var me = this;
20817
20818         me.list = {};
20819         me.zIndexStack = [];
20820         me.front = null;
20821
20822         if (container) {
20823
20824             
20825             if (container.isContainer) {
20826                 container.on('resize', me._onContainerResize, me);
20827                 me.zseed = Ext.Number.from(container.getEl().getStyle('zIndex'), me.getNextZSeed());
20828                 
20829                 me.targetEl = container.getTargetEl();
20830                 me.container = container;
20831             }
20832             
20833             else {
20834                 Ext.EventManager.onWindowResize(me._onContainerResize, me);
20835                 me.zseed = me.getNextZSeed();
20836                 me.targetEl = Ext.get(container);
20837             }
20838         }
20839         
20840         
20841         else {
20842             Ext.EventManager.onWindowResize(me._onContainerResize, me);
20843             me.zseed = me.getNextZSeed();
20844             Ext.onDocumentReady(function() {
20845                 me.targetEl = Ext.getBody();
20846             });
20847         }
20848     },
20849
20850     getNextZSeed: function() {
20851         return (Ext.ZIndexManager.zBase += 10000);
20852     },
20853
20854     setBase: function(baseZIndex) {
20855         this.zseed = baseZIndex;
20856         return this.assignZIndices();
20857     },
20858
20859     
20860     assignZIndices: function() {
20861         var a = this.zIndexStack,
20862             len = a.length,
20863             i = 0,
20864             zIndex = this.zseed,
20865             comp;
20866
20867         for (; i < len; i++) {
20868             comp = a[i];
20869             if (comp && !comp.hidden) {
20870
20871                 
20872                 
20873                 
20874                 
20875                 
20876                 
20877                 
20878                 zIndex = comp.setZIndex(zIndex);
20879             }
20880         }
20881         this._activateLast();
20882         return zIndex;
20883     },
20884
20885     
20886     _setActiveChild: function(comp) {
20887         if (comp !== this.front) {
20888
20889             if (this.front) {
20890                 this.front.setActive(false, comp);
20891             }
20892             this.front = comp;
20893             if (comp) {
20894                 comp.setActive(true);
20895                 if (comp.modal) {
20896                     this._showModalMask(comp);
20897                 }
20898             }
20899         }
20900     },
20901
20902     
20903     _activateLast: function(justHidden) {
20904         var comp,
20905             lastActivated = false,
20906             i;
20907
20908         
20909         
20910         
20911         for (i = this.zIndexStack.length-1; i >= 0; --i) {
20912             comp = this.zIndexStack[i];
20913             if (!comp.hidden) {
20914                 if (!lastActivated) {
20915                     this._setActiveChild(comp);
20916                     lastActivated = true;
20917                 }
20918
20919                 
20920                 if (comp.modal) {
20921                     this._showModalMask(comp);
20922                     return;
20923                 }
20924             }
20925         }
20926
20927         
20928         
20929         this._hideModalMask();
20930         if (!lastActivated) {
20931             this._setActiveChild(null);
20932         }
20933     },
20934
20935     _showModalMask: function(comp) {
20936         var zIndex = comp.el.getStyle('zIndex') - 4,
20937             maskTarget = comp.floatParent ? comp.floatParent.getTargetEl() : Ext.get(comp.getEl().dom.parentNode),
20938             parentBox;
20939         
20940         if (!maskTarget) {
20941             return;
20942         }
20943         
20944         parentBox = maskTarget.getBox();
20945
20946         if (!this.mask) {
20947             this.mask = Ext.getBody().createChild({
20948                 cls: Ext.baseCSSPrefix + 'mask'
20949             });
20950             this.mask.setVisibilityMode(Ext.Element.DISPLAY);
20951             this.mask.on('click', this._onMaskClick, this);
20952         }
20953         if (maskTarget.dom === document.body) {
20954             parentBox.height = Ext.Element.getViewHeight();
20955         }
20956         maskTarget.addCls(Ext.baseCSSPrefix + 'body-masked');
20957         this.mask.setBox(parentBox);
20958         this.mask.setStyle('zIndex', zIndex);
20959         this.mask.show();
20960     },
20961
20962     _hideModalMask: function() {
20963         if (this.mask && this.mask.dom.parentNode) {
20964             Ext.get(this.mask.dom.parentNode).removeCls(Ext.baseCSSPrefix + 'body-masked');
20965             this.mask.hide();
20966         }
20967     },
20968
20969     _onMaskClick: function() {
20970         if (this.front) {
20971             this.front.focus();
20972         }
20973     },
20974
20975     _onContainerResize: function() {
20976         if (this.mask && this.mask.isVisible()) {
20977             this.mask.setSize(Ext.get(this.mask.dom.parentNode).getViewSize(true));
20978         }
20979     },
20980
20981     
20982     register : function(comp) {
20983         if (comp.zIndexManager) {
20984             comp.zIndexManager.unregister(comp);
20985         }
20986         comp.zIndexManager = this;
20987
20988         this.list[comp.id] = comp;
20989         this.zIndexStack.push(comp);
20990         comp.on('hide', this._activateLast, this);
20991     },
20992
20993     
20994     unregister : function(comp) {
20995         delete comp.zIndexManager;
20996         if (this.list && this.list[comp.id]) {
20997             delete this.list[comp.id];
20998             comp.un('hide', this._activateLast);
20999             Ext.Array.remove(this.zIndexStack, comp);
21000
21001             
21002             this._activateLast(comp);
21003         }
21004     },
21005
21006     
21007     get : function(id) {
21008         return typeof id == "object" ? id : this.list[id];
21009     },
21010
21011    
21012     bringToFront : function(comp) {
21013         comp = this.get(comp);
21014         if (comp !== this.front) {
21015             Ext.Array.remove(this.zIndexStack, comp);
21016             this.zIndexStack.push(comp);
21017             this.assignZIndices();
21018             return true;
21019         }
21020         if (comp.modal) {
21021             this._showModalMask(comp);
21022         }
21023         return false;
21024     },
21025
21026     
21027     sendToBack : function(comp) {
21028         comp = this.get(comp);
21029         Ext.Array.remove(this.zIndexStack, comp);
21030         this.zIndexStack.unshift(comp);
21031         this.assignZIndices();
21032         return comp;
21033     },
21034
21035     
21036     hideAll : function() {
21037         for (var id in this.list) {
21038             if (this.list[id].isComponent && this.list[id].isVisible()) {
21039                 this.list[id].hide();
21040             }
21041         }
21042     },
21043
21044     
21045     hide: function() {
21046         var i = 0,
21047             ln = this.zIndexStack.length,
21048             comp;
21049
21050         this.tempHidden = [];
21051         for (; i < ln; i++) {
21052             comp = this.zIndexStack[i];
21053             if (comp.isVisible()) {
21054                 this.tempHidden.push(comp);
21055                 comp.hide();
21056             }
21057         }
21058     },
21059
21060     
21061     show: function() {
21062         var i = 0,
21063             ln = this.tempHidden.length,
21064             comp,
21065             x,
21066             y;
21067
21068         for (; i < ln; i++) {
21069             comp = this.tempHidden[i];
21070             x = comp.x;
21071             y = comp.y;
21072             comp.show();
21073             comp.setPosition(x, y);
21074         }
21075         delete this.tempHidden;
21076     },
21077
21078     
21079     getActive : function() {
21080         return this.front;
21081     },
21082
21083     
21084     getBy : function(fn, scope) {
21085         var r = [],
21086             i = 0,
21087             len = this.zIndexStack.length,
21088             comp;
21089
21090         for (; i < len; i++) {
21091             comp = this.zIndexStack[i];
21092             if (fn.call(scope||comp, comp) !== false) {
21093                 r.push(comp);
21094             }
21095         }
21096         return r;
21097     },
21098
21099     
21100     each : function(fn, scope) {
21101         var comp;
21102         for (var id in this.list) {
21103             comp = this.list[id];
21104             if (comp.isComponent && fn.call(scope || comp, comp) === false) {
21105                 return;
21106             }
21107         }
21108     },
21109
21110     
21111     eachBottomUp: function (fn, scope) {
21112         var comp,
21113             stack = this.zIndexStack,
21114             i, n;
21115
21116         for (i = 0, n = stack.length ; i < n; i++) {
21117             comp = stack[i];
21118             if (comp.isComponent && fn.call(scope || comp, comp) === false) {
21119                 return;
21120             }
21121         }
21122     },
21123
21124     
21125     eachTopDown: function (fn, scope) {
21126         var comp,
21127             stack = this.zIndexStack,
21128             i;
21129
21130         for (i = stack.length ; i-- > 0; ) {
21131             comp = stack[i];
21132             if (comp.isComponent && fn.call(scope || comp, comp) === false) {
21133                 return;
21134             }
21135         }
21136     },
21137
21138     destroy: function() {
21139         this.each(function(c) {
21140             c.destroy();
21141         });
21142         delete this.zIndexStack;
21143         delete this.list;
21144         delete this.container;
21145         delete this.targetEl;
21146     }
21147 }, function() {
21148     
21149     Ext.WindowManager = Ext.WindowMgr = new this();
21150 });
21151
21152
21153 Ext.define('Ext.layout.container.boxOverflow.None', {
21154     
21155     alternateClassName: 'Ext.layout.boxOverflow.None',
21156     
21157     constructor: function(layout, config) {
21158         this.layout = layout;
21159         Ext.apply(this, config || {});
21160     },
21161
21162     handleOverflow: Ext.emptyFn,
21163
21164     clearOverflow: Ext.emptyFn,
21165     
21166     onRemove: Ext.emptyFn,
21167
21168     
21169     getItem: function(item) {
21170         return this.layout.owner.getComponent(item);
21171     },
21172     
21173     onRemove: Ext.emptyFn
21174 });
21175
21176 Ext.define('Ext.util.KeyMap', {
21177     alternateClassName: 'Ext.KeyMap',
21178
21179     
21180     constructor: function(el, binding, eventName){
21181         var me = this;
21182
21183         Ext.apply(me, {
21184             el: Ext.get(el),
21185             eventName: eventName || me.eventName,
21186             bindings: []
21187         });
21188         if (binding) {
21189             me.addBinding(binding);
21190         }
21191         me.enable();
21192     },
21193
21194     eventName: 'keydown',
21195
21196     
21197     addBinding : function(binding){
21198         if (Ext.isArray(binding)) {
21199             Ext.each(binding, this.addBinding, this);
21200             return;
21201         }
21202
21203         var keyCode = binding.key,
21204             processed = false,
21205             key,
21206             keys,
21207             keyString,
21208             i,
21209             len;
21210
21211         if (Ext.isString(keyCode)) {
21212             keys = [];
21213             keyString = keyCode.toUpperCase();
21214
21215             for (i = 0, len = keyString.length; i < len; ++i){
21216                 keys.push(keyString.charCodeAt(i));
21217             }
21218             keyCode = keys;
21219             processed = true;
21220         }
21221
21222         if (!Ext.isArray(keyCode)) {
21223             keyCode = [keyCode];
21224         }
21225
21226         if (!processed) {
21227             for (i = 0, len = keyCode.length; i < len; ++i) {
21228                 key = keyCode[i];
21229                 if (Ext.isString(key)) {
21230                     keyCode[i] = key.toUpperCase().charCodeAt(0);
21231                 }
21232             }
21233         }
21234
21235         this.bindings.push(Ext.apply({
21236             keyCode: keyCode
21237         }, binding));
21238     },
21239
21240     
21241     handleKeyDown: function(event) {
21242         if (this.enabled) { 
21243             var bindings = this.bindings,
21244                 i = 0,
21245                 len = bindings.length;
21246
21247             event = this.processEvent(event);
21248             for(; i < len; ++i){
21249                 this.processBinding(bindings[i], event);
21250             }
21251         }
21252     },
21253
21254     
21255     processEvent: function(event){
21256         return event;
21257     },
21258
21259     
21260     processBinding: function(binding, event){
21261         if (this.checkModifiers(binding, event)) {
21262             var key = event.getKey(),
21263                 handler = binding.fn || binding.handler,
21264                 scope = binding.scope || this,
21265                 keyCode = binding.keyCode,
21266                 defaultEventAction = binding.defaultEventAction,
21267                 i,
21268                 len,
21269                 keydownEvent = new Ext.EventObjectImpl(event);
21270
21271
21272             for (i = 0, len = keyCode.length; i < len; ++i) {
21273                 if (key === keyCode[i]) {
21274                     if (handler.call(scope, key, event) !== true && defaultEventAction) {
21275                         keydownEvent[defaultEventAction]();
21276                     }
21277                     break;
21278                 }
21279             }
21280         }
21281     },
21282
21283     
21284     checkModifiers: function(binding, e){
21285         var keys = ['shift', 'ctrl', 'alt'],
21286             i = 0,
21287             len = keys.length,
21288             val, key;
21289
21290         for (; i < len; ++i){
21291             key = keys[i];
21292             val = binding[key];
21293             if (!(val === undefined || (val === e[key + 'Key']))) {
21294                 return false;
21295             }
21296         }
21297         return true;
21298     },
21299
21300     
21301     on: function(key, fn, scope) {
21302         var keyCode, shift, ctrl, alt;
21303         if (Ext.isObject(key) && !Ext.isArray(key)) {
21304             keyCode = key.key;
21305             shift = key.shift;
21306             ctrl = key.ctrl;
21307             alt = key.alt;
21308         } else {
21309             keyCode = key;
21310         }
21311         this.addBinding({
21312             key: keyCode,
21313             shift: shift,
21314             ctrl: ctrl,
21315             alt: alt,
21316             fn: fn,
21317             scope: scope
21318         });
21319     },
21320
21321     
21322     isEnabled : function(){
21323         return this.enabled;
21324     },
21325
21326     
21327     enable: function(){
21328         var me = this;
21329         
21330         if (!me.enabled) {
21331             me.el.on(me.eventName, me.handleKeyDown, me);
21332             me.enabled = true;
21333         }
21334     },
21335
21336     
21337     disable: function(){
21338         var me = this;
21339         
21340         if (me.enabled) {
21341             me.el.removeListener(me.eventName, me.handleKeyDown, me);
21342             me.enabled = false;
21343         }
21344     },
21345
21346     
21347     setDisabled : function(disabled){
21348         if (disabled) {
21349             this.disable();
21350         } else {
21351             this.enable();
21352         }
21353     },
21354
21355     
21356     destroy: function(removeEl){
21357         var me = this;
21358
21359         me.bindings = [];
21360         me.disable();
21361         if (removeEl === true) {
21362             me.el.remove();
21363         }
21364         delete me.el;
21365     }
21366 });
21367
21368 Ext.define('Ext.util.ClickRepeater', {
21369     extend: 'Ext.util.Observable',
21370
21371     
21372     constructor : function(el, config){
21373         this.el = Ext.get(el);
21374         this.el.unselectable();
21375
21376         Ext.apply(this, config);
21377
21378         this.addEvents(
21379         
21380         "mousedown",
21381         
21382         "click",
21383         
21384         "mouseup"
21385         );
21386
21387         if(!this.disabled){
21388             this.disabled = true;
21389             this.enable();
21390         }
21391
21392         
21393         if(this.handler){
21394             this.on("click", this.handler,  this.scope || this);
21395         }
21396
21397         this.callParent();
21398     },
21399
21400     
21401
21402     
21403
21404     
21405
21406     
21407     interval : 20,
21408
21409     
21410     delay: 250,
21411
21412     
21413     preventDefault : true,
21414     
21415     stopDefault : false,
21416
21417     timer : 0,
21418
21419     
21420     enable: function(){
21421         if(this.disabled){
21422             this.el.on('mousedown', this.handleMouseDown, this);
21423             if (Ext.isIE){
21424                 this.el.on('dblclick', this.handleDblClick, this);
21425             }
21426             if(this.preventDefault || this.stopDefault){
21427                 this.el.on('click', this.eventOptions, this);
21428             }
21429         }
21430         this.disabled = false;
21431     },
21432
21433     
21434     disable: function( force){
21435         if(force || !this.disabled){
21436             clearTimeout(this.timer);
21437             if(this.pressedCls){
21438                 this.el.removeCls(this.pressedCls);
21439             }
21440             Ext.getDoc().un('mouseup', this.handleMouseUp, this);
21441             this.el.removeAllListeners();
21442         }
21443         this.disabled = true;
21444     },
21445
21446     
21447     setDisabled: function(disabled){
21448         this[disabled ? 'disable' : 'enable']();
21449     },
21450
21451     eventOptions: function(e){
21452         if(this.preventDefault){
21453             e.preventDefault();
21454         }
21455         if(this.stopDefault){
21456             e.stopEvent();
21457         }
21458     },
21459
21460     
21461     destroy : function() {
21462         this.disable(true);
21463         Ext.destroy(this.el);
21464         this.clearListeners();
21465     },
21466
21467     handleDblClick : function(e){
21468         clearTimeout(this.timer);
21469         this.el.blur();
21470
21471         this.fireEvent("mousedown", this, e);
21472         this.fireEvent("click", this, e);
21473     },
21474
21475     
21476     handleMouseDown : function(e){
21477         clearTimeout(this.timer);
21478         this.el.blur();
21479         if(this.pressedCls){
21480             this.el.addCls(this.pressedCls);
21481         }
21482         this.mousedownTime = new Date();
21483
21484         Ext.getDoc().on("mouseup", this.handleMouseUp, this);
21485         this.el.on("mouseout", this.handleMouseOut, this);
21486
21487         this.fireEvent("mousedown", this, e);
21488         this.fireEvent("click", this, e);
21489
21490         
21491         if (this.accelerate) {
21492             this.delay = 400;
21493         }
21494
21495         
21496         
21497         e = new Ext.EventObjectImpl(e);
21498
21499         this.timer =  Ext.defer(this.click, this.delay || this.interval, this, [e]);
21500     },
21501
21502     
21503     click : function(e){
21504         this.fireEvent("click", this, e);
21505         this.timer =  Ext.defer(this.click, this.accelerate ?
21506             this.easeOutExpo(Ext.Date.getElapsed(this.mousedownTime),
21507                 400,
21508                 -390,
21509                 12000) :
21510             this.interval, this, [e]);
21511     },
21512
21513     easeOutExpo : function (t, b, c, d) {
21514         return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
21515     },
21516
21517     
21518     handleMouseOut : function(){
21519         clearTimeout(this.timer);
21520         if(this.pressedCls){
21521             this.el.removeCls(this.pressedCls);
21522         }
21523         this.el.on("mouseover", this.handleMouseReturn, this);
21524     },
21525
21526     
21527     handleMouseReturn : function(){
21528         this.el.un("mouseover", this.handleMouseReturn, this);
21529         if(this.pressedCls){
21530             this.el.addCls(this.pressedCls);
21531         }
21532         this.click();
21533     },
21534
21535     
21536     handleMouseUp : function(e){
21537         clearTimeout(this.timer);
21538         this.el.un("mouseover", this.handleMouseReturn, this);
21539         this.el.un("mouseout", this.handleMouseOut, this);
21540         Ext.getDoc().un("mouseup", this.handleMouseUp, this);
21541         if(this.pressedCls){
21542             this.el.removeCls(this.pressedCls);
21543         }
21544         this.fireEvent("mouseup", this, e);
21545     }
21546 });
21547
21548
21549 Ext.define('Ext.layout.component.Component', {
21550
21551     
21552
21553     extend: 'Ext.layout.Layout',
21554
21555     
21556
21557     type: 'component',
21558
21559     monitorChildren: true,
21560
21561     initLayout : function() {
21562         var me = this,
21563             owner = me.owner,
21564             ownerEl = owner.el;
21565
21566         if (!me.initialized) {
21567             if (owner.frameSize) {
21568                 me.frameSize = owner.frameSize;
21569             }
21570             else {
21571                 owner.frameSize = me.frameSize = {
21572                     top: 0,
21573                     left: 0,
21574                     bottom: 0,
21575                     right: 0
21576                 };
21577             }
21578         }
21579         me.callParent(arguments);
21580     },
21581
21582     beforeLayout : function(width, height, isSetSize, callingContainer) {
21583         this.callParent(arguments);
21584
21585         var me = this,
21586             owner = me.owner,
21587             ownerCt = owner.ownerCt,
21588             layout = owner.layout,
21589             isVisible = owner.isVisible(true),
21590             ownerElChild = owner.el.child,
21591             layoutCollection;
21592
21593         
21594         me.previousComponentSize = me.lastComponentSize;
21595
21596         
21597         if (!isSetSize
21598             && ((!Ext.isNumber(width) && owner.isFixedWidth()) ||
21599                 (!Ext.isNumber(height) && owner.isFixedHeight()))
21600             
21601             && callingContainer && callingContainer !== ownerCt) {
21602             
21603             me.doContainerLayout();
21604             return false;
21605         }
21606
21607         
21608         
21609         if (!isVisible && (owner.hiddenAncestor || owner.floating)) {
21610             if (owner.hiddenAncestor) {
21611                 layoutCollection = owner.hiddenAncestor.layoutOnShow;
21612                 layoutCollection.remove(owner);
21613                 layoutCollection.add(owner);
21614             }
21615             owner.needsLayout = {
21616                 width: width,
21617                 height: height,
21618                 isSetSize: false
21619             };
21620         }
21621
21622         if (isVisible && this.needsLayout(width, height)) {
21623             return owner.beforeComponentLayout(width, height, isSetSize, callingContainer);
21624         }
21625         else {
21626             return false;
21627         }
21628     },
21629
21630     
21631     needsLayout : function(width, height) {
21632         var me = this,
21633             widthBeingChanged,
21634             heightBeingChanged;
21635             me.lastComponentSize = me.lastComponentSize || {
21636                 width: -Infinity,
21637                 height: -Infinity
21638             };
21639
21640         
21641         widthBeingChanged  = !Ext.isDefined(width)  || me.lastComponentSize.width  !== width;
21642
21643         
21644         heightBeingChanged = !Ext.isDefined(height) || me.lastComponentSize.height !== height;
21645
21646
21647         
21648         return !me.isSizing && (me.childrenChanged || widthBeingChanged || heightBeingChanged);
21649     },
21650
21651     
21652     setElementSize: function(el, width, height) {
21653         if (width !== undefined && height !== undefined) {
21654             el.setSize(width, height);
21655         }
21656         else if (height !== undefined) {
21657             el.setHeight(height);
21658         }
21659         else if (width !== undefined) {
21660             el.setWidth(width);
21661         }
21662     },
21663
21664     
21665      getTarget : function() {
21666          return this.owner.el;
21667      },
21668
21669     
21670     getRenderTarget : function() {
21671         return this.owner.el;
21672     },
21673
21674     
21675     setTargetSize : function(width, height) {
21676         var me = this;
21677         me.setElementSize(me.owner.el, width, height);
21678
21679         if (me.owner.frameBody) {
21680             var targetInfo = me.getTargetInfo(),
21681                 padding = targetInfo.padding,
21682                 border = targetInfo.border,
21683                 frameSize = me.frameSize;
21684
21685             me.setElementSize(me.owner.frameBody,
21686                 Ext.isNumber(width) ? (width - frameSize.left - frameSize.right - padding.left - padding.right - border.left - border.right) : width,
21687                 Ext.isNumber(height) ? (height - frameSize.top - frameSize.bottom - padding.top - padding.bottom - border.top - border.bottom) : height
21688             );
21689         }
21690
21691         me.autoSized = {
21692             width: !Ext.isNumber(width),
21693             height: !Ext.isNumber(height)
21694         };
21695
21696         me.lastComponentSize = {
21697             width: width,
21698             height: height
21699         };
21700     },
21701
21702     getTargetInfo : function() {
21703         if (!this.targetInfo) {
21704             var target = this.getTarget(),
21705                 body = this.owner.getTargetEl();
21706
21707             this.targetInfo = {
21708                 padding: {
21709                     top: target.getPadding('t'),
21710                     right: target.getPadding('r'),
21711                     bottom: target.getPadding('b'),
21712                     left: target.getPadding('l')
21713                 },
21714                 border: {
21715                     top: target.getBorderWidth('t'),
21716                     right: target.getBorderWidth('r'),
21717                     bottom: target.getBorderWidth('b'),
21718                     left: target.getBorderWidth('l')
21719                 },
21720                 bodyMargin: {
21721                     top: body.getMargin('t'),
21722                     right: body.getMargin('r'),
21723                     bottom: body.getMargin('b'),
21724                     left: body.getMargin('l')
21725                 }
21726             };
21727         }
21728         return this.targetInfo;
21729     },
21730
21731     
21732     doOwnerCtLayouts: function() {
21733         var owner = this.owner,
21734             ownerCt = owner.ownerCt,
21735             ownerCtComponentLayout, ownerCtContainerLayout,
21736             curSize = this.lastComponentSize,
21737             prevSize = this.previousComponentSize,
21738             widthChange  = (prevSize && curSize && Ext.isNumber(curSize.width )) ? curSize.width  !== prevSize.width  : true,
21739             heightChange = (prevSize && curSize && Ext.isNumber(curSize.height)) ? curSize.height !== prevSize.height : true;
21740
21741         
21742         if (!ownerCt || (!widthChange && !heightChange)) {
21743             return;
21744         }
21745
21746         ownerCtComponentLayout = ownerCt.componentLayout;
21747         ownerCtContainerLayout = ownerCt.layout;
21748
21749         if (!owner.floating && ownerCtComponentLayout && ownerCtComponentLayout.monitorChildren && !ownerCtComponentLayout.layoutBusy) {
21750             if (!ownerCt.suspendLayout && ownerCtContainerLayout && !ownerCtContainerLayout.layoutBusy) {
21751
21752                 
21753                 if (((widthChange && !ownerCt.isFixedWidth()) || (heightChange && !ownerCt.isFixedHeight()))) {
21754                     
21755                     this.isSizing = true;
21756                     ownerCt.doComponentLayout();
21757                     this.isSizing = false;
21758                 }
21759                 
21760                 else if (ownerCtContainerLayout.bindToOwnerCtContainer === true) {
21761                     ownerCtContainerLayout.layout();
21762                 }
21763             }
21764         }
21765     },
21766
21767     doContainerLayout: function() {
21768         var me = this,
21769             owner = me.owner,
21770             ownerCt = owner.ownerCt,
21771             layout = owner.layout,
21772             ownerCtComponentLayout;
21773
21774         
21775         
21776         if (!owner.suspendLayout && layout && layout.isLayout && !layout.layoutBusy && !layout.isAutoDock) {
21777             layout.layout();
21778         }
21779
21780         
21781         if (ownerCt && ownerCt.componentLayout) {
21782             ownerCtComponentLayout = ownerCt.componentLayout;
21783             if (!owner.floating && ownerCtComponentLayout.monitorChildren && !ownerCtComponentLayout.layoutBusy) {
21784                 ownerCtComponentLayout.childrenChanged = true;
21785             }
21786         }
21787     },
21788
21789     afterLayout : function(width, height, isSetSize, layoutOwner) {
21790         this.doContainerLayout();
21791         this.owner.afterComponentLayout(width, height, isSetSize, layoutOwner);
21792     }
21793 });
21794
21795
21796 Ext.define('Ext.util.TextMetrics', {
21797     statics: {
21798         shared: null,
21799         
21800         measure: function(el, text, fixedWidth){
21801             var me = this,
21802                 shared = me.shared;
21803             
21804             if(!shared){
21805                 shared = me.shared = new me(el, fixedWidth);
21806             }
21807             shared.bind(el);
21808             shared.setFixedWidth(fixedWidth || 'auto');
21809             return shared.getSize(text);
21810         },
21811         
21812         
21813          destroy: function(){
21814              var me = this;
21815              Ext.destroy(me.shared);
21816              me.shared = null;
21817          }
21818     },
21819     
21820     
21821     constructor: function(bindTo, fixedWidth){
21822         var measure = this.measure = Ext.getBody().createChild({
21823             cls: 'x-textmetrics'
21824         });
21825         this.el = Ext.get(bindTo);
21826         
21827         measure.position('absolute');
21828         measure.setLeftTop(-1000, -1000);
21829         measure.hide();
21830
21831         if (fixedWidth) {
21832            measure.setWidth(fixedWidth);
21833         }
21834     },
21835     
21836     
21837     getSize: function(text){
21838         var measure = this.measure,
21839             size;
21840         
21841         measure.update(text);
21842         size = measure.getSize();
21843         measure.update('');
21844         return size;
21845     },
21846     
21847     
21848     bind: function(el){
21849         var me = this;
21850         
21851         me.el = Ext.get(el);
21852         me.measure.setStyle(
21853             me.el.getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing')
21854         );
21855     },
21856     
21857     
21858      setFixedWidth : function(width){
21859          this.measure.setWidth(width);
21860      },
21861      
21862      
21863      getWidth : function(text){
21864          this.measure.dom.style.width = 'auto';
21865          return this.getSize(text).width;
21866      },
21867      
21868      
21869      getHeight : function(text){
21870          return this.getSize(text).height;
21871      },
21872      
21873      
21874      destroy: function(){
21875          var me = this;
21876          me.measure.remove();
21877          delete me.el;
21878          delete me.measure;
21879      }
21880 }, function(){
21881     Ext.Element.addMethods({
21882         
21883         getTextWidth : function(text, min, max){
21884             return Ext.Number.constrain(Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width, min || 0, max || 1000000);
21885         }
21886     });
21887 });
21888
21889
21890 Ext.define('Ext.layout.container.boxOverflow.Scroller', {
21891
21892     
21893
21894     extend: 'Ext.layout.container.boxOverflow.None',
21895     requires: ['Ext.util.ClickRepeater', 'Ext.Element'],
21896     alternateClassName: 'Ext.layout.boxOverflow.Scroller',
21897     mixins: {
21898         observable: 'Ext.util.Observable'
21899     },
21900     
21901     
21902
21903     
21904     animateScroll: false,
21905
21906     
21907     scrollIncrement: 20,
21908
21909     
21910     wheelIncrement: 10,
21911
21912     
21913     scrollRepeatInterval: 60,
21914
21915     
21916     scrollDuration: 400,
21917
21918     
21919
21920     
21921
21922     
21923     scrollerCls: Ext.baseCSSPrefix + 'box-scroller',
21924
21925     
21926
21927     
21928     
21929     constructor: function(layout, config) {
21930         this.layout = layout;
21931         Ext.apply(this, config || {});
21932         
21933         this.addEvents(
21934             
21935             'scroll'
21936         );
21937     },
21938     
21939     initCSSClasses: function() {
21940         var me = this,
21941         layout = me.layout;
21942
21943         if (!me.CSSinitialized) {
21944             me.beforeCtCls = me.beforeCtCls || Ext.baseCSSPrefix + 'box-scroller-' + layout.parallelBefore;
21945             me.afterCtCls  = me.afterCtCls  || Ext.baseCSSPrefix + 'box-scroller-' + layout.parallelAfter;
21946             me.beforeScrollerCls = me.beforeScrollerCls || Ext.baseCSSPrefix + layout.owner.getXType() + '-scroll-' + layout.parallelBefore;
21947             me.afterScrollerCls  = me.afterScrollerCls  || Ext.baseCSSPrefix + layout.owner.getXType() + '-scroll-' + layout.parallelAfter;
21948             me.CSSinitializes = true;
21949         }
21950     },
21951
21952     handleOverflow: function(calculations, targetSize) {
21953         var me = this,
21954             layout = me.layout,
21955             methodName = 'get' + layout.parallelPrefixCap,
21956             newSize = {};
21957
21958         me.initCSSClasses();
21959         me.callParent(arguments);
21960         this.createInnerElements();
21961         this.showScrollers();
21962         newSize[layout.perpendicularPrefix] = targetSize[layout.perpendicularPrefix];
21963         newSize[layout.parallelPrefix] = targetSize[layout.parallelPrefix] - (me.beforeCt[methodName]() + me.afterCt[methodName]());
21964         return { targetSize: newSize };
21965     },
21966
21967     
21968     createInnerElements: function() {
21969         var me = this,
21970             target = me.layout.getRenderTarget();
21971
21972         
21973         
21974         if (!me.beforeCt) {
21975             target.addCls(Ext.baseCSSPrefix + me.layout.direction + '-box-overflow-body');
21976             me.beforeCt = target.insertSibling({cls: Ext.layout.container.Box.prototype.innerCls + ' ' + me.beforeCtCls}, 'before');
21977             me.afterCt  = target.insertSibling({cls: Ext.layout.container.Box.prototype.innerCls + ' ' + me.afterCtCls},  'after');
21978             me.createWheelListener();
21979         }
21980     },
21981
21982     
21983     createWheelListener: function() {
21984         this.layout.innerCt.on({
21985             scope     : this,
21986             mousewheel: function(e) {
21987                 e.stopEvent();
21988
21989                 this.scrollBy(e.getWheelDelta() * this.wheelIncrement * -1, false);
21990             }
21991         });
21992     },
21993
21994     
21995     clearOverflow: function() {
21996         this.hideScrollers();
21997     },
21998
21999     
22000     showScrollers: function() {
22001         this.createScrollers();
22002         this.beforeScroller.show();
22003         this.afterScroller.show();
22004         this.updateScrollButtons();
22005         
22006         this.layout.owner.addClsWithUI('scroller');
22007     },
22008
22009     
22010     hideScrollers: function() {
22011         if (this.beforeScroller != undefined) {
22012             this.beforeScroller.hide();
22013             this.afterScroller.hide();
22014             
22015             this.layout.owner.removeClsWithUI('scroller');
22016         }
22017     },
22018
22019     
22020     createScrollers: function() {
22021         if (!this.beforeScroller && !this.afterScroller) {
22022             var before = this.beforeCt.createChild({
22023                 cls: Ext.String.format("{0} {1} ", this.scrollerCls, this.beforeScrollerCls)
22024             });
22025
22026             var after = this.afterCt.createChild({
22027                 cls: Ext.String.format("{0} {1}", this.scrollerCls, this.afterScrollerCls)
22028             });
22029
22030             before.addClsOnOver(this.beforeScrollerCls + '-hover');
22031             after.addClsOnOver(this.afterScrollerCls + '-hover');
22032
22033             before.setVisibilityMode(Ext.Element.DISPLAY);
22034             after.setVisibilityMode(Ext.Element.DISPLAY);
22035
22036             this.beforeRepeater = Ext.create('Ext.util.ClickRepeater', before, {
22037                 interval: this.scrollRepeatInterval,
22038                 handler : this.scrollLeft,
22039                 scope   : this
22040             });
22041
22042             this.afterRepeater = Ext.create('Ext.util.ClickRepeater', after, {
22043                 interval: this.scrollRepeatInterval,
22044                 handler : this.scrollRight,
22045                 scope   : this
22046             });
22047
22048             
22049             this.beforeScroller = before;
22050
22051             
22052             this.afterScroller = after;
22053         }
22054     },
22055
22056     
22057     destroy: function() {
22058         Ext.destroy(this.beforeRepeater, this.afterRepeater, this.beforeScroller, this.afterScroller, this.beforeCt, this.afterCt);
22059     },
22060
22061     
22062     scrollBy: function(delta, animate) {
22063         this.scrollTo(this.getScrollPosition() + delta, animate);
22064     },
22065
22066     
22067     getScrollAnim: function() {
22068         return {
22069             duration: this.scrollDuration, 
22070             callback: this.updateScrollButtons, 
22071             scope   : this
22072         };
22073     },
22074
22075     
22076     updateScrollButtons: function() {
22077         if (this.beforeScroller == undefined || this.afterScroller == undefined) {
22078             return;
22079         }
22080
22081         var beforeMeth = this.atExtremeBefore()  ? 'addCls' : 'removeCls',
22082             afterMeth  = this.atExtremeAfter() ? 'addCls' : 'removeCls',
22083             beforeCls  = this.beforeScrollerCls + '-disabled',
22084             afterCls   = this.afterScrollerCls  + '-disabled';
22085         
22086         this.beforeScroller[beforeMeth](beforeCls);
22087         this.afterScroller[afterMeth](afterCls);
22088         this.scrolling = false;
22089     },
22090
22091     
22092     atExtremeBefore: function() {
22093         return this.getScrollPosition() === 0;
22094     },
22095
22096     
22097     scrollLeft: function() {
22098         this.scrollBy(-this.scrollIncrement, false);
22099     },
22100
22101     
22102     scrollRight: function() {
22103         this.scrollBy(this.scrollIncrement, false);
22104     },
22105
22106     
22107     getScrollPosition: function(){
22108         var layout = this.layout;
22109         return parseInt(layout.innerCt.dom['scroll' + layout.parallelBeforeCap], 10) || 0;
22110     },
22111
22112     
22113     getMaxScrollPosition: function() {
22114         var layout = this.layout;
22115         return layout.innerCt.dom['scroll' + layout.parallelPrefixCap] - this.layout.innerCt['get' + layout.parallelPrefixCap]();
22116     },
22117
22118     
22119     atExtremeAfter: function() {
22120         return this.getScrollPosition() >= this.getMaxScrollPosition();
22121     },
22122
22123     
22124     scrollTo: function(position, animate) {
22125         var me = this,
22126             layout = me.layout,
22127             oldPosition = me.getScrollPosition(),
22128             newPosition = Ext.Number.constrain(position, 0, me.getMaxScrollPosition());
22129
22130         if (newPosition != oldPosition && !me.scrolling) {
22131             if (animate == undefined) {
22132                 animate = me.animateScroll;
22133             }
22134
22135             layout.innerCt.scrollTo(layout.parallelBefore, newPosition, animate ? me.getScrollAnim() : false);
22136             if (animate) {
22137                 me.scrolling = true;
22138             } else {
22139                 me.scrolling = false;
22140                 me.updateScrollButtons();
22141             }
22142             
22143             me.fireEvent('scroll', me, newPosition, animate ? me.getScrollAnim() : false);
22144         }
22145     },
22146
22147     
22148     scrollToItem: function(item, animate) {
22149         var me = this,
22150             layout = me.layout,
22151             visibility,
22152             box,
22153             newPos;
22154
22155         item = me.getItem(item);
22156         if (item != undefined) {
22157             visibility = this.getItemVisibility(item);
22158             if (!visibility.fullyVisible) {
22159                 box  = item.getBox(true, true);
22160                 newPos = box[layout.parallelPosition];
22161                 if (visibility.hiddenEnd) {
22162                     newPos -= (this.layout.innerCt['get' + layout.parallelPrefixCap]() - box[layout.parallelPrefix]);
22163                 }
22164                 this.scrollTo(newPos, animate);
22165             }
22166         }
22167     },
22168
22169     
22170     getItemVisibility: function(item) {
22171         var me          = this,
22172             box         = me.getItem(item).getBox(true, true),
22173             layout      = me.layout,
22174             itemStart   = box[layout.parallelPosition],
22175             itemEnd     = itemStart + box[layout.parallelPrefix],
22176             scrollStart = me.getScrollPosition(),
22177             scrollEnd   = scrollStart + layout.innerCt['get' + layout.parallelPrefixCap]();
22178
22179         return {
22180             hiddenStart : itemStart < scrollStart,
22181             hiddenEnd   : itemEnd > scrollEnd,
22182             fullyVisible: itemStart > scrollStart && itemEnd < scrollEnd
22183         };
22184     }
22185 });
22186
22187 Ext.define('Ext.util.Offset', {
22188
22189     
22190
22191     statics: {
22192         fromObject: function(obj) {
22193             return new this(obj.x, obj.y);
22194         }
22195     },
22196
22197     
22198
22199     constructor: function(x, y) {
22200         this.x = (x != null && !isNaN(x)) ? x : 0;
22201         this.y = (y != null && !isNaN(y)) ? y : 0;
22202
22203         return this;
22204     },
22205
22206     copy: function() {
22207         return new Ext.util.Offset(this.x, this.y);
22208     },
22209
22210     copyFrom: function(p) {
22211         this.x = p.x;
22212         this.y = p.y;
22213     },
22214
22215     toString: function() {
22216         return "Offset[" + this.x + "," + this.y + "]";
22217     },
22218
22219     equals: function(offset) {
22220
22221         return (this.x == offset.x && this.y == offset.y);
22222     },
22223
22224     round: function(to) {
22225         if (!isNaN(to)) {
22226             var factor = Math.pow(10, to);
22227             this.x = Math.round(this.x * factor) / factor;
22228             this.y = Math.round(this.y * factor) / factor;
22229         } else {
22230             this.x = Math.round(this.x);
22231             this.y = Math.round(this.y);
22232         }
22233     },
22234
22235     isZero: function() {
22236         return this.x == 0 && this.y == 0;
22237     }
22238 });
22239
22240
22241 Ext.define('Ext.util.KeyNav', {
22242     
22243     alternateClassName: 'Ext.KeyNav',
22244     
22245     requires: ['Ext.util.KeyMap'],
22246     
22247     statics: {
22248         keyOptions: {
22249             left: 37,
22250             right: 39,
22251             up: 38,
22252             down: 40,
22253             space: 32,
22254             pageUp: 33,
22255             pageDown: 34,
22256             del: 46,
22257             backspace: 8,
22258             home: 36,
22259             end: 35,
22260             enter: 13,
22261             esc: 27,
22262             tab: 9
22263         }
22264     },
22265
22266     
22267     constructor: function(el, config){
22268         this.setConfig(el, config || {});
22269     },
22270     
22271     
22272     setConfig: function(el, config) {
22273         if (this.map) {
22274             this.map.destroy();
22275         }
22276         
22277         var map = Ext.create('Ext.util.KeyMap', el, null, this.getKeyEvent('forceKeyDown' in config ? config.forceKeyDown : this.forceKeyDown)),
22278             keys = Ext.util.KeyNav.keyOptions,
22279             scope = config.scope || this,
22280             key;
22281         
22282         this.map = map;
22283         for (key in keys) {
22284             if (keys.hasOwnProperty(key)) {
22285                 if (config[key]) {
22286                     map.addBinding({
22287                         scope: scope,
22288                         key: keys[key],
22289                         handler: Ext.Function.bind(this.handleEvent, scope, [config[key]], true),
22290                         defaultEventAction: config.defaultEventAction || this.defaultEventAction
22291                     });
22292                 }
22293             }
22294         }
22295         
22296         map.disable();
22297         if (!config.disabled) {
22298             map.enable();
22299         }
22300     },
22301     
22302     
22303     handleEvent: function(map, event, handler){
22304         return handler.call(this, event);
22305     },
22306     
22307     
22308     disabled: false,
22309     
22310     
22311     defaultEventAction: "stopEvent",
22312     
22313     
22314     forceKeyDown: false,
22315     
22316     
22317     destroy: function(removeEl){
22318         this.map.destroy(removeEl);
22319         delete this.map;
22320     },
22321
22322     
22323     enable: function() {
22324         this.map.enable();
22325         this.disabled = false;
22326     },
22327
22328     
22329     disable: function() {
22330         this.map.disable();
22331         this.disabled = true;
22332     },
22333     
22334     
22335     setDisabled : function(disabled){
22336         this.map.setDisabled(disabled);
22337         this.disabled = disabled;
22338     },
22339     
22340     
22341     getKeyEvent: function(forceKeyDown){
22342         return (forceKeyDown || Ext.EventManager.useKeyDown) ? 'keydown' : 'keypress';
22343     }
22344 });
22345
22346
22347
22348 Ext.define('Ext.fx.Queue', {
22349
22350     requires: ['Ext.util.HashMap'],
22351
22352     constructor: function() {
22353         this.targets = Ext.create('Ext.util.HashMap');
22354         this.fxQueue = {};
22355     },
22356
22357     
22358     getFxDefaults: function(targetId) {
22359         var target = this.targets.get(targetId);
22360         if (target) {
22361             return target.fxDefaults;
22362         }
22363         return {};
22364     },
22365
22366     
22367     setFxDefaults: function(targetId, obj) {
22368         var target = this.targets.get(targetId);
22369         if (target) {
22370             target.fxDefaults = Ext.apply(target.fxDefaults || {}, obj);
22371         }
22372     },
22373
22374     
22375     stopAnimation: function(targetId) {
22376         var me = this,
22377             queue = me.getFxQueue(targetId),
22378             ln = queue.length;
22379         while (ln) {
22380             queue[ln - 1].end();
22381             ln--;
22382         }
22383     },
22384
22385     
22386     getActiveAnimation: function(targetId) {
22387         var queue = this.getFxQueue(targetId);
22388         return (queue && !!queue.length) ? queue[0] : false;
22389     },
22390
22391     
22392     hasFxBlock: function(targetId) {
22393         var queue = this.getFxQueue(targetId);
22394         return queue && queue[0] && queue[0].block;
22395     },
22396
22397     
22398     getFxQueue: function(targetId) {
22399         if (!targetId) {
22400             return false;
22401         }
22402         var me = this,
22403             queue = me.fxQueue[targetId],
22404             target = me.targets.get(targetId);
22405
22406         if (!target) {
22407             return false;
22408         }
22409
22410         if (!queue) {
22411             me.fxQueue[targetId] = [];
22412             
22413             if (target.type != 'element') {
22414                 target.target.on('destroy', function() {
22415                     me.fxQueue[targetId] = [];
22416                 });
22417             }
22418         }
22419         return me.fxQueue[targetId];
22420     },
22421
22422     
22423     queueFx: function(anim) {
22424         var me = this,
22425             target = anim.target,
22426             queue, ln;
22427
22428         if (!target) {
22429             return;
22430         }
22431
22432         queue = me.getFxQueue(target.getId());
22433         ln = queue.length;
22434
22435         if (ln) {
22436             if (anim.concurrent) {
22437                 anim.paused = false;
22438             }
22439             else {
22440                 queue[ln - 1].on('afteranimate', function() {
22441                     anim.paused = false;
22442                 });
22443             }
22444         }
22445         else {
22446             anim.paused = false;
22447         }
22448         anim.on('afteranimate', function() {
22449             Ext.Array.remove(queue, anim);
22450             if (anim.remove) {
22451                 if (target.type == 'element') {
22452                     var el = Ext.get(target.id);
22453                     if (el) {
22454                         el.remove();
22455                     }
22456                 }
22457             }
22458         }, this);
22459         queue.push(anim);
22460     }
22461 });
22462
22463 Ext.define('Ext.fx.target.Target', {
22464
22465     isAnimTarget: true,
22466
22467     
22468     constructor: function(target) {
22469         this.target = target;
22470         this.id = this.getId();
22471     },
22472     
22473     getId: function() {
22474         return this.target.id;
22475     }
22476 });
22477
22478
22479
22480 Ext.define('Ext.fx.target.Sprite', {
22481
22482     
22483
22484     extend: 'Ext.fx.target.Target',
22485
22486     
22487
22488     type: 'draw',
22489
22490     getFromPrim: function(sprite, attr) {
22491         var o;
22492         if (attr == 'translate') {
22493             o = {
22494                 x: sprite.attr.translation.x || 0,
22495                 y: sprite.attr.translation.y || 0
22496             };
22497         }
22498         else if (attr == 'rotate') {
22499             o = {
22500                 degrees: sprite.attr.rotation.degrees || 0,
22501                 x: sprite.attr.rotation.x,
22502                 y: sprite.attr.rotation.y
22503             };
22504         }
22505         else {
22506             o = sprite.attr[attr];
22507         }
22508         return o;
22509     },
22510
22511     getAttr: function(attr, val) {
22512         return [[this.target, val != undefined ? val : this.getFromPrim(this.target, attr)]];
22513     },
22514
22515     setAttr: function(targetData) {
22516         var ln = targetData.length,
22517             spriteArr = [],
22518             attrs, attr, attrArr, attPtr, spritePtr, idx, value, i, j, x, y, ln2;
22519         for (i = 0; i < ln; i++) {
22520             attrs = targetData[i].attrs;
22521             for (attr in attrs) {
22522                 attrArr = attrs[attr];
22523                 ln2 = attrArr.length;
22524                 for (j = 0; j < ln2; j++) {
22525                     spritePtr = attrArr[j][0];
22526                     attPtr = attrArr[j][1];
22527                     if (attr === 'translate') {
22528                         value = {
22529                             x: attPtr.x,
22530                             y: attPtr.y
22531                         };
22532                     }
22533                     else if (attr === 'rotate') {
22534                         x = attPtr.x;
22535                         if (isNaN(x)) {
22536                             x = null;
22537                         }
22538                         y = attPtr.y;
22539                         if (isNaN(y)) {
22540                             y = null;
22541                         }
22542                         value = {
22543                             degrees: attPtr.degrees,
22544                             x: x,
22545                             y: y
22546                         };
22547                     }
22548                     else if (attr === 'width' || attr === 'height' || attr === 'x' || attr === 'y') {
22549                         value = parseFloat(attPtr);
22550                     }
22551                     else {
22552                         value = attPtr;
22553                     }
22554                     idx = Ext.Array.indexOf(spriteArr, spritePtr);
22555                     if (idx == -1) {
22556                         spriteArr.push([spritePtr, {}]);
22557                         idx = spriteArr.length - 1;
22558                     }
22559                     spriteArr[idx][1][attr] = value;
22560                 }
22561             }
22562         }
22563         ln = spriteArr.length;
22564         for (i = 0; i < ln; i++) {
22565             spritePtr = spriteArr[i];
22566             spritePtr[0].setAttributes(spritePtr[1]);
22567         }
22568         this.target.redraw();
22569     }
22570 });
22571
22572
22573
22574 Ext.define('Ext.fx.target.CompositeSprite', {
22575
22576     
22577
22578     extend: 'Ext.fx.target.Sprite',
22579
22580     
22581
22582     getAttr: function(attr, val) {
22583         var out = [],
22584             target = this.target;
22585         target.each(function(sprite) {
22586             out.push([sprite, val != undefined ? val : this.getFromPrim(sprite, attr)]);
22587         }, this);
22588         return out;
22589     }
22590 });
22591
22592
22593 Ext.define('Ext.fx.target.Component', {
22594
22595     
22596    
22597     extend: 'Ext.fx.target.Target',
22598     
22599     
22600
22601     type: 'component',
22602
22603     
22604     getPropMethod: {
22605         top: function() {
22606             return this.getPosition(true)[1];
22607         },
22608         left: function() {
22609             return this.getPosition(true)[0];
22610         },
22611         x: function() {
22612             return this.getPosition()[0];
22613         },
22614         y: function() {
22615             return this.getPosition()[1];
22616         },
22617         height: function() {
22618             return this.getHeight();
22619         },
22620         width: function() {
22621             return this.getWidth();
22622         },
22623         opacity: function() {
22624             return this.el.getStyle('opacity');
22625         }
22626     },
22627
22628     compMethod: {
22629         top: 'setPosition',
22630         left: 'setPosition',
22631         x: 'setPagePosition',
22632         y: 'setPagePosition',
22633         height: 'setSize',
22634         width: 'setSize',
22635         opacity: 'setOpacity'
22636     },
22637
22638     
22639     getAttr: function(attr, val) {
22640         return [[this.target, val !== undefined ? val : this.getPropMethod[attr].call(this.target)]];
22641     },
22642
22643     setAttr: function(targetData, isFirstFrame, isLastFrame) {
22644         var me = this,
22645             target = me.target,
22646             ln = targetData.length,
22647             attrs, attr, o, i, j, meth, targets, left, top, w, h;
22648         for (i = 0; i < ln; i++) {
22649             attrs = targetData[i].attrs;
22650             for (attr in attrs) {
22651                 targets = attrs[attr].length;
22652                 meth = {
22653                     setPosition: {},
22654                     setPagePosition: {},
22655                     setSize: {},
22656                     setOpacity: {}
22657                 };
22658                 for (j = 0; j < targets; j++) {
22659                     o = attrs[attr][j];
22660                     
22661                     
22662                     
22663                     
22664                     meth[me.compMethod[attr]].target = o[0];
22665                     meth[me.compMethod[attr]][attr] = o[1];
22666                 }
22667                 if (meth.setPosition.target) {
22668                     o = meth.setPosition;
22669                     left = (o.left === undefined) ? undefined : parseInt(o.left, 10);
22670                     top = (o.top === undefined) ? undefined : parseInt(o.top, 10);
22671                     o.target.setPosition(left, top);
22672                 }
22673                 if (meth.setPagePosition.target) {
22674                     o = meth.setPagePosition;
22675                     o.target.setPagePosition(o.x, o.y);
22676                 }
22677                 if (meth.setSize.target && meth.setSize.target.el) {
22678                     o = meth.setSize;
22679                     
22680                     w = (o.width === undefined) ? o.target.getWidth() : parseInt(o.width, 10);
22681                     h = (o.height === undefined) ? o.target.getHeight() : parseInt(o.height, 10);
22682
22683                     
22684                     
22685                     
22686                     
22687                     
22688                     
22689                     
22690                     if (isLastFrame || me.dynamic) {
22691                         o.target.componentLayout.childrenChanged = true;
22692
22693                         
22694                         if (me.layoutAnimation) {
22695                             o.target.setCalculatedSize(w, h);
22696                         } else {
22697                             o.target.setSize(w, h);
22698                         }
22699                     }
22700                     else {
22701                         o.target.el.setSize(w, h);
22702                     }
22703                 }
22704                 if (meth.setOpacity.target) {
22705                     o = meth.setOpacity;
22706                     o.target.el.setStyle('opacity', o.opacity);
22707                 }
22708             }
22709         }
22710     }
22711 });
22712
22713
22714 Ext.define('Ext.fx.CubicBezier', {
22715
22716     
22717
22718     singleton: true,
22719
22720     
22721
22722     cubicBezierAtTime: function(t, p1x, p1y, p2x, p2y, duration) {
22723         var cx = 3 * p1x,
22724             bx = 3 * (p2x - p1x) - cx,
22725             ax = 1 - cx - bx,
22726             cy = 3 * p1y,
22727             by = 3 * (p2y - p1y) - cy,
22728             ay = 1 - cy - by;
22729         function sampleCurveX(t) {
22730             return ((ax * t + bx) * t + cx) * t;
22731         }
22732         function solve(x, epsilon) {
22733             var t = solveCurveX(x, epsilon);
22734             return ((ay * t + by) * t + cy) * t;
22735         }
22736         function solveCurveX(x, epsilon) {
22737             var t0, t1, t2, x2, d2, i;
22738             for (t2 = x, i = 0; i < 8; i++) {
22739                 x2 = sampleCurveX(t2) - x;
22740                 if (Math.abs(x2) < epsilon) {
22741                     return t2;
22742                 }
22743                 d2 = (3 * ax * t2 + 2 * bx) * t2 + cx;
22744                 if (Math.abs(d2) < 1e-6) {
22745                     break;
22746                 }
22747                 t2 = t2 - x2 / d2;
22748             }
22749             t0 = 0;
22750             t1 = 1;
22751             t2 = x;
22752             if (t2 < t0) {
22753                 return t0;
22754             }
22755             if (t2 > t1) {
22756                 return t1;
22757             }
22758             while (t0 < t1) {
22759                 x2 = sampleCurveX(t2);
22760                 if (Math.abs(x2 - x) < epsilon) {
22761                     return t2;
22762                 }
22763                 if (x > x2) {
22764                     t0 = t2;
22765                 } else {
22766                     t1 = t2;
22767                 }
22768                 t2 = (t1 - t0) / 2 + t0;
22769             }
22770             return t2;
22771         }
22772         return solve(t, 1 / (200 * duration));
22773     },
22774
22775     cubicBezier: function(x1, y1, x2, y2) {
22776         var fn = function(pos) {
22777             return Ext.fx.CubicBezier.cubicBezierAtTime(pos, x1, y1, x2, y2, 1);
22778         };
22779         fn.toCSS3 = function() {
22780             return 'cubic-bezier(' + [x1, y1, x2, y2].join(',') + ')';
22781         };
22782         fn.reverse = function() {
22783             return Ext.fx.CubicBezier.cubicBezier(1 - x2, 1 - y2, 1 - x1, 1 - y1);
22784         };
22785         return fn;
22786     }
22787 });
22788
22789 Ext.define('Ext.draw.Color', {
22790
22791     
22792
22793     
22794
22795     colorToHexRe: /(.*?)rgb\((\d+),\s*(\d+),\s*(\d+)\)/,
22796     rgbRe: /\s*rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)\s*/,
22797     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*/,
22798
22799     
22800     lightnessFactor: 0.2,
22801
22802     
22803     constructor : function(red, green, blue) {
22804         var me = this,
22805             clamp = Ext.Number.constrain;
22806         me.r = clamp(red, 0, 255);
22807         me.g = clamp(green, 0, 255);
22808         me.b = clamp(blue, 0, 255);
22809     },
22810
22811     
22812     getRed: function() {
22813         return this.r;
22814     },
22815
22816     
22817     getGreen: function() {
22818         return this.g;
22819     },
22820
22821     
22822     getBlue: function() {
22823         return this.b;
22824     },
22825
22826     
22827     getRGB: function() {
22828         var me = this;
22829         return [me.r, me.g, me.b];
22830     },
22831
22832     
22833     getHSL: function() {
22834         var me = this,
22835             r = me.r / 255,
22836             g = me.g / 255,
22837             b = me.b / 255,
22838             max = Math.max(r, g, b),
22839             min = Math.min(r, g, b),
22840             delta = max - min,
22841             h,
22842             s = 0,
22843             l = 0.5 * (max + min);
22844
22845         
22846         if (min != max) {
22847             s = (l < 0.5) ? delta / (max + min) : delta / (2 - max - min);
22848             if (r == max) {
22849                 h = 60 * (g - b) / delta;
22850             } else if (g == max) {
22851                 h = 120 + 60 * (b - r) / delta;
22852             } else {
22853                 h = 240 + 60 * (r - g) / delta;
22854             }
22855             if (h < 0) {
22856                 h += 360;
22857             }
22858             if (h >= 360) {
22859                 h -= 360;
22860             }
22861         }
22862         return [h, s, l];
22863     },
22864
22865     
22866     getLighter: function(factor) {
22867         var hsl = this.getHSL();
22868         factor = factor || this.lightnessFactor;
22869         hsl[2] = Ext.Number.constrain(hsl[2] + factor, 0, 1);
22870         return this.fromHSL(hsl[0], hsl[1], hsl[2]);
22871     },
22872
22873     
22874     getDarker: function(factor) {
22875         factor = factor || this.lightnessFactor;
22876         return this.getLighter(-factor);
22877     },
22878
22879     
22880     toString: function() {
22881         var me = this,
22882             round = Math.round,
22883             r = round(me.r).toString(16),
22884             g = round(me.g).toString(16),
22885             b = round(me.b).toString(16);
22886         r = (r.length == 1) ? '0' + r : r;
22887         g = (g.length == 1) ? '0' + g : g;
22888         b = (b.length == 1) ? '0' + b : b;
22889         return ['#', r, g, b].join('');
22890     },
22891
22892     
22893     toHex: function(color) {
22894         if (Ext.isArray(color)) {
22895             color = color[0];
22896         }
22897         if (!Ext.isString(color)) {
22898             return '';
22899         }
22900         if (color.substr(0, 1) === '#') {
22901             return color;
22902         }
22903         var digits = this.colorToHexRe.exec(color);
22904
22905         if (Ext.isArray(digits)) {
22906             var red = parseInt(digits[2], 10),
22907                 green = parseInt(digits[3], 10),
22908                 blue = parseInt(digits[4], 10),
22909                 rgb = blue | (green << 8) | (red << 16);
22910             return digits[1] + '#' + ("000000" + rgb.toString(16)).slice(-6);
22911         }
22912         else {
22913             return '';
22914         }
22915     },
22916
22917     
22918     fromString: function(str) {
22919         var values, r, g, b,
22920             parse = parseInt;
22921
22922         if ((str.length == 4 || str.length == 7) && str.substr(0, 1) === '#') {
22923             values = str.match(this.hexRe);
22924             if (values) {
22925                 r = parse(values[1], 16) >> 0;
22926                 g = parse(values[2], 16) >> 0;
22927                 b = parse(values[3], 16) >> 0;
22928                 if (str.length == 4) {
22929                     r += (r * 16);
22930                     g += (g * 16);
22931                     b += (b * 16);
22932                 }
22933             }
22934         }
22935         else {
22936             values = str.match(this.rgbRe);
22937             if (values) {
22938                 r = values[1];
22939                 g = values[2];
22940                 b = values[3];
22941             }
22942         }
22943
22944         return (typeof r == 'undefined') ? undefined : Ext.create('Ext.draw.Color', r, g, b);
22945     },
22946
22947     
22948     getGrayscale: function() {
22949         
22950         return this.r * 0.3 + this.g * 0.59 + this.b * 0.11;
22951     },
22952
22953     
22954     fromHSL: function(h, s, l) {
22955         var C, X, m, i, rgb = [],
22956             abs = Math.abs,
22957             floor = Math.floor;
22958
22959         if (s == 0 || h == null) {
22960             
22961             rgb = [l, l, l];
22962         }
22963         else {
22964             
22965             
22966             
22967             
22968             h /= 60;
22969             C = s * (1 - abs(2 * l - 1));
22970             X = C * (1 - abs(h - 2 * floor(h / 2) - 1));
22971             m = l - C / 2;
22972             switch (floor(h)) {
22973                 case 0:
22974                     rgb = [C, X, 0];
22975                     break;
22976                 case 1:
22977                     rgb = [X, C, 0];
22978                     break;
22979                 case 2:
22980                     rgb = [0, C, X];
22981                     break;
22982                 case 3:
22983                     rgb = [0, X, C];
22984                     break;
22985                 case 4:
22986                     rgb = [X, 0, C];
22987                     break;
22988                 case 5:
22989                     rgb = [C, 0, X];
22990                     break;
22991             }
22992             rgb = [rgb[0] + m, rgb[1] + m, rgb[2] + m];
22993         }
22994         return Ext.create('Ext.draw.Color', rgb[0] * 255, rgb[1] * 255, rgb[2] * 255);
22995     }
22996 }, function() {
22997     var prototype = this.prototype;
22998
22999     
23000     this.addStatics({
23001         fromHSL: function() {
23002             return prototype.fromHSL.apply(prototype, arguments);
23003         },
23004         fromString: function() {
23005             return prototype.fromString.apply(prototype, arguments);
23006         },
23007         toHex: function() {
23008             return prototype.toHex.apply(prototype, arguments);
23009         }
23010     });
23011 });
23012
23013
23014 Ext.define('Ext.dd.StatusProxy', {
23015     animRepair: false,
23016
23017     
23018     constructor: function(config){
23019         Ext.apply(this, config);
23020         this.id = this.id || Ext.id();
23021         this.proxy = Ext.createWidget('component', {
23022             floating: true,
23023             stateful: false,
23024             id: this.id,
23025             html: '<div class="' + Ext.baseCSSPrefix + 'dd-drop-icon"></div>' +
23026                   '<div class="' + Ext.baseCSSPrefix + 'dd-drag-ghost"></div>',
23027             cls: Ext.baseCSSPrefix + 'dd-drag-proxy ' + this.dropNotAllowed,
23028             shadow: !config || config.shadow !== false,
23029             renderTo: document.body
23030         });
23031
23032         this.el = this.proxy.el;
23033         this.el.show();
23034         this.el.setVisibilityMode(Ext.Element.VISIBILITY);
23035         this.el.hide();
23036
23037         this.ghost = Ext.get(this.el.dom.childNodes[1]);
23038         this.dropStatus = this.dropNotAllowed;
23039     },
23040     
23041     dropAllowed : Ext.baseCSSPrefix + 'dd-drop-ok',
23042     
23043     dropNotAllowed : Ext.baseCSSPrefix + 'dd-drop-nodrop',
23044
23045     
23046     setStatus : function(cssClass){
23047         cssClass = cssClass || this.dropNotAllowed;
23048         if(this.dropStatus != cssClass){
23049             this.el.replaceCls(this.dropStatus, cssClass);
23050             this.dropStatus = cssClass;
23051         }
23052     },
23053
23054     
23055     reset : function(clearGhost){
23056         this.el.dom.className = Ext.baseCSSPrefix + 'dd-drag-proxy ' + this.dropNotAllowed;
23057         this.dropStatus = this.dropNotAllowed;
23058         if(clearGhost){
23059             this.ghost.update("");
23060         }
23061     },
23062
23063     
23064     update : function(html){
23065         if(typeof html == "string"){
23066             this.ghost.update(html);
23067         }else{
23068             this.ghost.update("");
23069             html.style.margin = "0";
23070             this.ghost.dom.appendChild(html);
23071         }
23072         var el = this.ghost.dom.firstChild;
23073         if(el){
23074             Ext.fly(el).setStyle('float', 'none');
23075         }
23076     },
23077
23078     
23079     getEl : function(){
23080         return this.el;
23081     },
23082
23083     
23084     getGhost : function(){
23085         return this.ghost;
23086     },
23087
23088     
23089     hide : function(clear) {
23090         this.proxy.hide();
23091         if (clear) {
23092             this.reset(true);
23093         }
23094     },
23095
23096     
23097     stop : function(){
23098         if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
23099             this.anim.stop();
23100         }
23101     },
23102
23103     
23104     show : function() {
23105         this.proxy.show();
23106         this.proxy.toFront();
23107     },
23108
23109     
23110     sync : function(){
23111         this.proxy.el.sync();
23112     },
23113
23114     
23115     repair : function(xy, callback, scope){
23116         this.callback = callback;
23117         this.scope = scope;
23118         if (xy && this.animRepair !== false) {
23119             this.el.addCls(Ext.baseCSSPrefix + 'dd-drag-repair');
23120             this.el.hideUnders(true);
23121             this.anim = this.el.animate({
23122                 duration: this.repairDuration || 500,
23123                 easing: 'ease-out',
23124                 to: {
23125                     x: xy[0],
23126                     y: xy[1]
23127                 },
23128                 stopAnimation: true,
23129                 callback: this.afterRepair,
23130                 scope: this
23131             });
23132         } else {
23133             this.afterRepair();
23134         }
23135     },
23136
23137     
23138     afterRepair : function(){
23139         this.hide(true);
23140         if(typeof this.callback == "function"){
23141             this.callback.call(this.scope || this);
23142         }
23143         this.callback = null;
23144         this.scope = null;
23145     },
23146
23147     destroy: function(){
23148         Ext.destroy(this.ghost, this.proxy, this.el);
23149     }
23150 });
23151
23152 Ext.define('Ext.panel.Proxy', {
23153
23154     alternateClassName: 'Ext.dd.PanelProxy',
23155
23156     
23157     constructor: function(panel, config){
23158         
23159         this.panel = panel;
23160         this.id = this.panel.id +'-ddproxy';
23161         Ext.apply(this, config);
23162     },
23163
23164     
23165     insertProxy: true,
23166
23167     
23168     setStatus: Ext.emptyFn,
23169     reset: Ext.emptyFn,
23170     update: Ext.emptyFn,
23171     stop: Ext.emptyFn,
23172     sync: Ext.emptyFn,
23173
23174     
23175     getEl: function(){
23176         return this.ghost.el;
23177     },
23178
23179     
23180     getGhost: function(){
23181         return this.ghost;
23182     },
23183
23184     
23185     getProxy: function(){
23186         return this.proxy;
23187     },
23188
23189     
23190     hide : function(){
23191         if (this.ghost) {
23192             if (this.proxy) {
23193                 this.proxy.remove();
23194                 delete this.proxy;
23195             }
23196
23197             
23198             this.panel.unghost(null, false);
23199             delete this.ghost;
23200         }
23201     },
23202
23203     
23204     show: function(){
23205         if (!this.ghost) {
23206             var panelSize = this.panel.getSize();
23207             this.panel.el.setVisibilityMode(Ext.Element.DISPLAY);
23208             this.ghost = this.panel.ghost();
23209             if (this.insertProxy) {
23210                 
23211                 
23212                 this.proxy = this.panel.el.insertSibling({cls: Ext.baseCSSPrefix + 'panel-dd-spacer'});
23213                 this.proxy.setSize(panelSize);
23214             }
23215         }
23216     },
23217
23218     
23219     repair: function(xy, callback, scope) {
23220         this.hide();
23221         if (typeof callback == "function") {
23222             callback.call(scope || this);
23223         }
23224     },
23225
23226     
23227     moveProxy : function(parentNode, before){
23228         if (this.proxy) {
23229             parentNode.insertBefore(this.proxy.dom, before);
23230         }
23231     }
23232 });
23233
23234
23235 Ext.define('Ext.layout.component.AbstractDock', {
23236
23237     
23238
23239     extend: 'Ext.layout.component.Component',
23240
23241     
23242
23243     type: 'dock',
23244
23245     
23246     autoSizing: true,
23247
23248     beforeLayout: function() {
23249         var returnValue = this.callParent(arguments);
23250         if (returnValue !== false && (!this.initializedBorders || this.childrenChanged) && (!this.owner.border || this.owner.manageBodyBorders)) {
23251             this.handleItemBorders();
23252             this.initializedBorders = true;
23253         }
23254         return returnValue;
23255     },
23256     
23257     handleItemBorders: function() {
23258         var owner = this.owner,
23259             body = owner.body,
23260             docked = this.getLayoutItems(),
23261             borders = {
23262                 top: [],
23263                 right: [],
23264                 bottom: [],
23265                 left: []
23266             },
23267             oldBorders = this.borders,
23268             opposites = {
23269                 top: 'bottom',
23270                 right: 'left',
23271                 bottom: 'top',
23272                 left: 'right'
23273             },
23274             i, ln, item, dock, side;
23275
23276         for (i = 0, ln = docked.length; i < ln; i++) {
23277             item = docked[i];
23278             dock = item.dock;
23279             
23280             if (item.ignoreBorderManagement) {
23281                 continue;
23282             }
23283             
23284             if (!borders[dock].satisfied) {
23285                 borders[dock].push(item);
23286                 borders[dock].satisfied = true;
23287             }
23288             
23289             if (!borders.top.satisfied && opposites[dock] !== 'top') {
23290                 borders.top.push(item);
23291             }
23292             if (!borders.right.satisfied && opposites[dock] !== 'right') {
23293                 borders.right.push(item);
23294             }            
23295             if (!borders.bottom.satisfied && opposites[dock] !== 'bottom') {
23296                 borders.bottom.push(item);
23297             }            
23298             if (!borders.left.satisfied && opposites[dock] !== 'left') {
23299                 borders.left.push(item);
23300             }
23301         }
23302
23303         if (oldBorders) {
23304             for (side in oldBorders) {
23305                 if (oldBorders.hasOwnProperty(side)) {
23306                     ln = oldBorders[side].length;
23307                     if (!owner.manageBodyBorders) {
23308                         for (i = 0; i < ln; i++) {
23309                             oldBorders[side][i].removeCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
23310                         }
23311                         if (!oldBorders[side].satisfied && !owner.bodyBorder) {
23312                             body.removeCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);                   
23313                         }                    
23314                     }
23315                     else if (oldBorders[side].satisfied) {
23316                         body.setStyle('border-' + side + '-width', '');
23317                     }
23318                 }
23319             }
23320         }
23321                 
23322         for (side in borders) {
23323             if (borders.hasOwnProperty(side)) {
23324                 ln = borders[side].length;
23325                 if (!owner.manageBodyBorders) {
23326                     for (i = 0; i < ln; i++) {
23327                         borders[side][i].addCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
23328                     }
23329                     if ((!borders[side].satisfied && !owner.bodyBorder) || owner.bodyBorder === false) {
23330                         body.addCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);                   
23331                     }                    
23332                 }
23333                 else if (borders[side].satisfied) {
23334                     body.setStyle('border-' + side + '-width', '1px');
23335                 }
23336             }
23337         }
23338         
23339         this.borders = borders;
23340     },
23341     
23342     
23343     onLayout: function(width, height) {
23344         if (this.onLayout_running) {
23345             return;
23346         }
23347         this.onLayout_running = true;
23348         var me = this,
23349             owner = me.owner,
23350             body = owner.body,
23351             layout = owner.layout,
23352             target = me.getTarget(),
23353             autoWidth = false,
23354             autoHeight = false,
23355             padding, border, frameSize;
23356
23357         
23358         var info = me.info = {
23359             boxes: [],
23360             size: {
23361                 width: width,
23362                 height: height
23363             },
23364             bodyBox: {}
23365         };
23366         
23367         delete layout.isAutoDock;
23368
23369         Ext.applyIf(info, me.getTargetInfo());
23370
23371         
23372         if (owner && owner.ownerCt && owner.ownerCt.layout && owner.ownerCt.layout.isLayout) {
23373             if (!Ext.isNumber(owner.height) || !Ext.isNumber(owner.width)) {
23374                 owner.ownerCt.layout.bindToOwnerCtComponent = true;
23375             }
23376             else {
23377                 owner.ownerCt.layout.bindToOwnerCtComponent = false;
23378             }
23379         }
23380
23381         
23382         if (height == null || width == null) {
23383             padding = info.padding;
23384             border = info.border;
23385             frameSize = me.frameSize;
23386
23387             
23388             if ((height == null) && (width == null)) {
23389                 autoHeight = true;
23390                 autoWidth = true;
23391                 me.setTargetSize(null);
23392                 me.setBodyBox({width: null, height: null});
23393             }
23394             
23395             else if (height == null) {
23396                 autoHeight = true;
23397                 
23398                 me.setTargetSize(width);
23399                 me.setBodyBox({width: width - padding.left - border.left - padding.right - border.right - frameSize.left - frameSize.right, height: null});
23400             
23401             }
23402             else {
23403                 autoWidth = true;
23404                 
23405                 me.setTargetSize(null, height);
23406                 me.setBodyBox({width: null, height: height - padding.top - padding.bottom - border.top - border.bottom - frameSize.top - frameSize.bottom});
23407             }
23408
23409             
23410             if (layout && layout.isLayout) {
23411                 
23412                 layout.bindToOwnerCtComponent = true;
23413                 
23414                 layout.isAutoDock = layout.autoSize !== true;
23415                 layout.layout();
23416
23417                 
23418                 
23419                 
23420                 
23421                 
23422                 
23423                 
23424                 
23425                 
23426                 
23427                 
23428                 
23429                 info.autoSizedCtLayout = layout.autoSize === true;
23430                 info.autoHeight = autoHeight;
23431                 info.autoWidth = autoWidth;
23432             }
23433
23434             
23435             
23436             
23437             
23438             
23439             me.dockItems();
23440             me.setTargetSize(info.size.width, info.size.height);
23441         }
23442         else {
23443             me.setTargetSize(width, height);
23444             me.dockItems();
23445         }
23446         me.callParent(arguments);
23447         this.onLayout_running = false;
23448     },
23449
23450     
23451     dockItems : function() {
23452         this.calculateDockBoxes();
23453
23454         
23455         
23456         
23457         var info = this.info,
23458             autoWidth = info.autoWidth,
23459             autoHeight = info.autoHeight,
23460             boxes = info.boxes,
23461             ln = boxes.length,
23462             dock, i, item;
23463
23464         
23465         
23466         for (i = 0; i < ln; i++) {
23467             dock = boxes[i];
23468             item = dock.item;
23469             item.setPosition(dock.x, dock.y);
23470             if ((autoWidth || autoHeight) && item.layout && item.layout.isLayout) {
23471                 
23472                 item.layout.bindToOwnerCtComponent = true;
23473             }
23474         }
23475
23476         
23477         
23478         if (!info.autoSizedCtLayout) {
23479             if (autoWidth) {
23480                 info.bodyBox.width = null;
23481             }
23482             if (autoHeight) {
23483                 info.bodyBox.height = null;
23484             }
23485         }
23486
23487         
23488         
23489         this.setBodyBox(info.bodyBox);
23490     },
23491
23492     
23493     calculateDockBoxes : function() {
23494         if (this.calculateDockBoxes_running) {
23495             
23496             return;
23497         }
23498         this.calculateDockBoxes_running = true;
23499         
23500         
23501         
23502         var me = this,
23503             target = me.getTarget(),
23504             items = me.getLayoutItems(),
23505             owner = me.owner,
23506             bodyEl = owner.body,
23507             info = me.info,
23508             autoWidth = info.autoWidth,
23509             autoHeight = info.autoHeight,
23510             size = info.size,
23511             ln = items.length,
23512             padding = info.padding,
23513             border = info.border,
23514             frameSize = me.frameSize,
23515             item, i, box, rect;
23516
23517         
23518         
23519         if (autoHeight) {
23520             size.height = bodyEl.getHeight() + padding.top + border.top + padding.bottom + border.bottom + frameSize.top + frameSize.bottom;
23521         }
23522         else {
23523             size.height = target.getHeight();
23524         }
23525         if (autoWidth) {
23526             size.width = bodyEl.getWidth() + padding.left + border.left + padding.right + border.right + frameSize.left + frameSize.right;
23527         }
23528         else {
23529             size.width = target.getWidth();
23530         }
23531
23532         info.bodyBox = {
23533             x: padding.left + frameSize.left,
23534             y: padding.top + frameSize.top,
23535             width: size.width - padding.left - border.left - padding.right - border.right - frameSize.left - frameSize.right,
23536             height: size.height - border.top - padding.top - border.bottom - padding.bottom - frameSize.top - frameSize.bottom
23537         };
23538
23539         
23540         for (i = 0; i < ln; i++) {
23541             item = items[i];
23542             
23543             
23544             
23545             box = me.initBox(item);
23546
23547             if (autoHeight === true) {
23548                 box = me.adjustAutoBox(box, i);
23549             }
23550             else {
23551                 box = me.adjustSizedBox(box, i);
23552             }
23553
23554             
23555             
23556             
23557             info.boxes.push(box);
23558         }
23559         this.calculateDockBoxes_running = false;
23560     },
23561
23562     
23563     adjustSizedBox : function(box, index) {
23564         var bodyBox = this.info.bodyBox,
23565             frameSize = this.frameSize,
23566             info = this.info,
23567             padding = info.padding,
23568             pos = box.type,
23569             border = info.border;
23570
23571         switch (pos) {
23572             case 'top':
23573                 box.y = bodyBox.y;
23574                 break;
23575
23576             case 'left':
23577                 box.x = bodyBox.x;
23578                 break;
23579
23580             case 'bottom':
23581                 box.y = (bodyBox.y + bodyBox.height) - box.height;
23582                 break;
23583
23584             case 'right':
23585                 box.x = (bodyBox.x + bodyBox.width) - box.width;
23586                 break;
23587         }
23588
23589         if (box.ignoreFrame) {
23590             if (pos == 'bottom') {
23591                 box.y += (frameSize.bottom + padding.bottom + border.bottom);
23592             }
23593             else {
23594                 box.y -= (frameSize.top + padding.top + border.top);
23595             }
23596             if (pos == 'right') {
23597                 box.x += (frameSize.right + padding.right + border.right);
23598             }
23599             else {
23600                 box.x -= (frameSize.left + padding.left + border.left);
23601             }
23602         }
23603
23604         
23605         if (!box.overlay) {
23606             switch (pos) {
23607                 case 'top':
23608                     bodyBox.y += box.height;
23609                     bodyBox.height -= box.height;
23610                     break;
23611
23612                 case 'left':
23613                     bodyBox.x += box.width;
23614                     bodyBox.width -= box.width;
23615                     break;
23616
23617                 case 'bottom':
23618                     bodyBox.height -= box.height;
23619                     break;
23620
23621                 case 'right':
23622                     bodyBox.width -= box.width;
23623                     break;
23624             }
23625         }
23626         return box;
23627     },
23628
23629     
23630     adjustAutoBox : function (box, index) {
23631         var info = this.info,
23632             owner = this.owner,
23633             bodyBox = info.bodyBox,
23634             size = info.size,
23635             boxes = info.boxes,
23636             boxesLn = boxes.length,
23637             pos = box.type,
23638             frameSize = this.frameSize,
23639             padding = info.padding,
23640             border = info.border,
23641             autoSizedCtLayout = info.autoSizedCtLayout,
23642             ln = (boxesLn < index) ? boxesLn : index,
23643             i, adjustBox;
23644
23645         if (pos == 'top' || pos == 'bottom') {
23646             
23647             for (i = 0; i < ln; i++) {
23648                 adjustBox = boxes[i];
23649                 if (adjustBox.stretched && adjustBox.type == 'left' || adjustBox.type == 'right') {
23650                     adjustBox.height += box.height;
23651                 }
23652                 else if (adjustBox.type == 'bottom') {
23653                     adjustBox.y += box.height;
23654                 }
23655             }
23656         }
23657
23658         switch (pos) {
23659             case 'top':
23660                 box.y = bodyBox.y;
23661                 if (!box.overlay) {
23662                     bodyBox.y += box.height;
23663                     if (info.autoHeight) {
23664                         size.height += box.height;
23665                     } else {
23666                         bodyBox.height -= box.height;
23667                     }
23668                 }
23669                 break;
23670
23671             case 'bottom':
23672                 if (!box.overlay) {
23673                     if (info.autoHeight) {
23674                         size.height += box.height;
23675                     } else {
23676                         bodyBox.height -= box.height;
23677                     }
23678                 }
23679                 box.y = (bodyBox.y + bodyBox.height);
23680                 break;
23681
23682             case 'left':
23683                 box.x = bodyBox.x;
23684                 if (!box.overlay) {
23685                     bodyBox.x += box.width;
23686                     if (info.autoWidth) {
23687                         size.width += box.width;
23688                     } else {
23689                         bodyBox.width -= box.width;
23690                     }
23691                 }
23692                 break;
23693
23694             case 'right':
23695                 if (!box.overlay) {
23696                     if (info.autoWidth) {
23697                         size.width += box.width;
23698                     } else {
23699                         bodyBox.width -= box.width;
23700                     }
23701                 }
23702                 box.x = (bodyBox.x + bodyBox.width);
23703                 break;
23704         }
23705
23706         if (box.ignoreFrame) {
23707             if (pos == 'bottom') {
23708                 box.y += (frameSize.bottom + padding.bottom + border.bottom);
23709             }
23710             else {
23711                 box.y -= (frameSize.top + padding.top + border.top);
23712             }
23713             if (pos == 'right') {
23714                 box.x += (frameSize.right + padding.right + border.right);
23715             }
23716             else {
23717                 box.x -= (frameSize.left + padding.left + border.left);
23718             }
23719         }
23720         return box;
23721     },
23722
23723     
23724     initBox : function(item) {
23725         var me = this,
23726             bodyBox = me.info.bodyBox,
23727             horizontal = (item.dock == 'top' || item.dock == 'bottom'),
23728             owner = me.owner,
23729             frameSize = me.frameSize,
23730             info = me.info,
23731             padding = info.padding,
23732             border = info.border,
23733             box = {
23734                 item: item,
23735                 overlay: item.overlay,
23736                 type: item.dock,
23737                 offsets: Ext.Element.parseBox(item.offsets || {}),
23738                 ignoreFrame: item.ignoreParentFrame
23739             };
23740         
23741         if (item.stretch !== false) {
23742             box.stretched = true;
23743             if (horizontal) {
23744                 box.x = bodyBox.x + box.offsets.left;
23745                 box.width = bodyBox.width - (box.offsets.left + box.offsets.right);
23746                 if (box.ignoreFrame) {
23747                     box.width += (frameSize.left + frameSize.right + border.left + border.right + padding.left + padding.right);
23748                 }
23749                 item.setCalculatedSize(box.width - item.el.getMargin('lr'), undefined, owner);
23750             }
23751             else {
23752                 box.y = bodyBox.y + box.offsets.top;
23753                 box.height = bodyBox.height - (box.offsets.bottom + box.offsets.top);
23754                 if (box.ignoreFrame) {
23755                     box.height += (frameSize.top + frameSize.bottom + border.top + border.bottom + padding.top + padding.bottom);
23756                 }
23757                 item.setCalculatedSize(undefined, box.height - item.el.getMargin('tb'), owner);
23758
23759                 
23760                 
23761                 if (!Ext.supports.ComputedStyle) {
23762                     item.el.repaint();
23763                 }
23764             }
23765         }
23766         else {
23767             item.doComponentLayout();
23768             box.width = item.getWidth() - (box.offsets.left + box.offsets.right);
23769             box.height = item.getHeight() - (box.offsets.bottom + box.offsets.top);
23770             box.y += box.offsets.top;
23771             if (horizontal) {
23772                 box.x = (item.align == 'right') ? bodyBox.width - box.width : bodyBox.x;
23773                 box.x += box.offsets.left;
23774             }
23775         }
23776
23777         
23778         
23779         if (box.width === undefined) {
23780             box.width = item.getWidth() + item.el.getMargin('lr');
23781         }
23782         if (box.height === undefined) {
23783             box.height = item.getHeight() + item.el.getMargin('tb');
23784         }
23785
23786         return box;
23787     },
23788
23789     
23790     getLayoutItems : function() {
23791         var it = this.owner.getDockedItems(),
23792             ln = it.length,
23793             i = 0,
23794             result = [];
23795         for (; i < ln; i++) {
23796             if (it[i].isVisible(true)) {
23797                 result.push(it[i]);
23798             }
23799         }
23800         return result;
23801     },
23802
23803     
23804     renderItems: function(items, target) {
23805         var cns = target.dom.childNodes,
23806             cnsLn = cns.length,
23807             ln = items.length,
23808             domLn = 0,
23809             i, j, cn, item;
23810
23811         
23812         for (i = 0; i < cnsLn; i++) {
23813             cn = Ext.get(cns[i]);
23814             for (j = 0; j < ln; j++) {
23815                 item = items[j];
23816                 if (item.rendered && (cn.id == item.el.id || cn.contains(item.el.id))) {
23817                     break;
23818                 }
23819             }
23820
23821             if (j === ln) {
23822                 domLn++;
23823             }
23824         }
23825
23826         
23827         for (i = 0, j = 0; i < ln; i++, j++) {
23828             item = items[i];
23829
23830             
23831             
23832             
23833             
23834             
23835             
23836             
23837             
23838             if (i === j && (item.dock === 'right' || item.dock === 'bottom')) {
23839                 j += domLn;
23840             }
23841
23842             
23843             if (item && !item.rendered) {
23844                 this.renderItem(item, target, j);
23845             }
23846             else if (!this.isValidParent(item, target, j)) {
23847                 this.moveItem(item, target, j);
23848             }
23849         }
23850     },
23851
23852     
23853     setBodyBox : function(box) {
23854         var me = this,
23855             owner = me.owner,
23856             body = owner.body,
23857             info = me.info,
23858             bodyMargin = info.bodyMargin,
23859             padding = info.padding,
23860             border = info.border,
23861             frameSize = me.frameSize;
23862         
23863         
23864         if (owner.collapsed) {
23865             return;
23866         }
23867         
23868         if (Ext.isNumber(box.width)) {
23869             box.width -= bodyMargin.left + bodyMargin.right;
23870         }
23871         
23872         if (Ext.isNumber(box.height)) {
23873             box.height -= bodyMargin.top + bodyMargin.bottom;
23874         }
23875         
23876         me.setElementSize(body, box.width, box.height);
23877         if (Ext.isNumber(box.x)) {
23878             body.setLeft(box.x - padding.left - frameSize.left);
23879         }
23880         if (Ext.isNumber(box.y)) {
23881             body.setTop(box.y - padding.top - frameSize.top);
23882         }
23883     },
23884
23885     
23886     configureItem : function(item, pos) {
23887         this.callParent(arguments);
23888         if (item.dock == 'top' || item.dock == 'bottom') {
23889             item.layoutManagedWidth = 1;
23890             item.layoutManagedHeight = 2;
23891         } else {
23892             item.layoutManagedWidth = 2;
23893             item.layoutManagedHeight = 1;
23894         }
23895         
23896         item.addCls(Ext.baseCSSPrefix + 'docked');
23897         item.addClsWithUI('docked-' + item.dock);
23898     },
23899
23900     afterRemove : function(item) {
23901         this.callParent(arguments);
23902         if (this.itemCls) {
23903             item.el.removeCls(this.itemCls + '-' + item.dock);
23904         }
23905         var dom = item.el.dom;
23906
23907         if (!item.destroying && dom) {
23908             dom.parentNode.removeChild(dom);
23909         }
23910         this.childrenChanged = true;
23911     }
23912 });
23913
23914 Ext.define('Ext.util.Memento', function () {
23915
23916     function captureOne (src, target, prop) {
23917         src[prop] = target[prop];
23918     }
23919
23920     function removeOne (src, target, prop) {
23921         delete src[prop];
23922     }
23923
23924     function restoreOne (src, target, prop) {
23925         var value = src[prop];
23926         if (value || src.hasOwnProperty(prop)) {
23927             restoreValue(target, prop, value);
23928         }
23929     }
23930
23931     function restoreValue (target, prop, value) {
23932         if (Ext.isDefined(value)) {
23933             target[prop] = value;
23934         } else {
23935             delete target[prop];
23936         }
23937     }
23938
23939     function doMany (doOne, src, target, props) {
23940         if (src) {
23941             if (Ext.isArray(props)) {
23942                 Ext.each(props, function (prop) {
23943                     doOne(src, target, prop);
23944                 });
23945             } else {
23946                 doOne(src, target, props);
23947             }
23948         }
23949     }
23950
23951     return {
23952         
23953         data: null,
23954
23955         
23956         target: null,
23957
23958         
23959         constructor: function (target, props) {
23960             if (target) {
23961                 this.target = target;
23962                 if (props) {
23963                     this.capture(props);
23964                 }
23965             }
23966         },
23967
23968         
23969         capture: function (props, target) {
23970             doMany(captureOne, this.data || (this.data = {}), target || this.target, props);
23971         },
23972
23973         
23974         remove: function (props) {
23975             doMany(removeOne, this.data, null, props);
23976         },
23977
23978         
23979         restore: function (props, clear, target) {
23980             doMany(restoreOne, this.data, target || this.target, props);
23981             if (clear !== false) {
23982                 this.remove(props);
23983             }
23984         },
23985
23986         
23987         restoreAll: function (clear, target) {
23988             var me = this,
23989                 t = target || this.target;
23990
23991             Ext.Object.each(me.data, function (prop, value) {
23992                 restoreValue(t, prop, value);
23993             });
23994
23995             if (clear !== false) {
23996                 delete me.data;
23997             }
23998         }
23999     };
24000 }());
24001
24002
24003 Ext.define('Ext.app.EventBus', {
24004     requires: [
24005         'Ext.util.Event'
24006     ],
24007     mixins: {
24008         observable: 'Ext.util.Observable'
24009     },
24010
24011     constructor: function() {
24012         this.mixins.observable.constructor.call(this);
24013
24014         this.bus = {};
24015
24016         var me = this;
24017         Ext.override(Ext.Component, {
24018             fireEvent: function(ev) {
24019                 if (Ext.util.Observable.prototype.fireEvent.apply(this, arguments) !== false) {
24020                     return me.dispatch.call(me, ev, this, arguments);
24021                 }
24022                 return false;
24023             }
24024         });
24025     },
24026
24027     dispatch: function(ev, target, args) {
24028         var bus = this.bus,
24029             selectors = bus[ev],
24030             selector, controllers, id, events, event, i, ln;
24031
24032         if (selectors) {
24033             
24034             for (selector in selectors) {
24035                 
24036                 if (target.is(selector)) {
24037                     
24038                     controllers = selectors[selector];
24039                     for (id in controllers) {
24040                         
24041                         events = controllers[id];
24042                         for (i = 0, ln = events.length; i < ln; i++) {
24043                             event = events[i];
24044                             
24045                             if (event.fire.apply(event, Array.prototype.slice.call(args, 1)) === false) {
24046                                 return false;
24047                             };
24048                         }
24049                     }
24050                 }
24051             }
24052         }
24053     },
24054
24055     control: function(selectors, listeners, controller) {
24056         var bus = this.bus,
24057             selector, fn;
24058
24059         if (Ext.isString(selectors)) {
24060             selector = selectors;
24061             selectors = {};
24062             selectors[selector] = listeners;
24063             this.control(selectors, null, controller);
24064             return;
24065         }
24066
24067         Ext.Object.each(selectors, function(selector, listeners) {
24068             Ext.Object.each(listeners, function(ev, listener) {
24069                 var options = {},
24070                     scope = controller,
24071                     event = Ext.create('Ext.util.Event', controller, ev);
24072
24073                 
24074                 if (Ext.isObject(listener)) {
24075                     options = listener;
24076                     listener = options.fn;
24077                     scope = options.scope || controller;
24078                     delete options.fn;
24079                     delete options.scope;
24080                 }
24081
24082                 event.addListener(listener, scope, options);
24083
24084                 
24085                 bus[ev] = bus[ev] || {};
24086                 bus[ev][selector] = bus[ev][selector] || {};
24087                 bus[ev][selector][controller.id] = bus[ev][selector][controller.id] || [];
24088
24089                 
24090                 bus[ev][selector][controller.id].push(event);
24091             });
24092         });
24093     }
24094 });
24095
24096 Ext.define('Ext.data.Types', {
24097     singleton: true,
24098     requires: ['Ext.data.SortTypes']
24099 }, function() {
24100     var st = Ext.data.SortTypes;
24101
24102     Ext.apply(Ext.data.Types, {
24103         
24104         stripRe: /[\$,%]/g,
24105
24106         
24107         AUTO: {
24108             convert: function(v) {
24109                 return v;
24110             },
24111             sortType: st.none,
24112             type: 'auto'
24113         },
24114
24115         
24116         STRING: {
24117             convert: function(v) {
24118                 var defaultValue = this.useNull ? null : '';
24119                 return (v === undefined || v === null) ? defaultValue : String(v);
24120             },
24121             sortType: st.asUCString,
24122             type: 'string'
24123         },
24124
24125         
24126         INT: {
24127             convert: function(v) {
24128                 return v !== undefined && v !== null && v !== '' ?
24129                     parseInt(String(v).replace(Ext.data.Types.stripRe, ''), 10) : (this.useNull ? null : 0);
24130             },
24131             sortType: st.none,
24132             type: 'int'
24133         },
24134
24135         
24136         FLOAT: {
24137             convert: function(v) {
24138                 return v !== undefined && v !== null && v !== '' ?
24139                     parseFloat(String(v).replace(Ext.data.Types.stripRe, ''), 10) : (this.useNull ? null : 0);
24140             },
24141             sortType: st.none,
24142             type: 'float'
24143         },
24144
24145         
24146         BOOL: {
24147             convert: function(v) {
24148                 if (this.useNull && (v === undefined || v === null || v === '')) {
24149                     return null;
24150                 }
24151                 return v === true || v === 'true' || v == 1;
24152             },
24153             sortType: st.none,
24154             type: 'bool'
24155         },
24156
24157         
24158         DATE: {
24159             convert: function(v) {
24160                 var df = this.dateFormat,
24161                     parsed;
24162
24163                 if (!v) {
24164                     return null;
24165                 }
24166                 if (Ext.isDate(v)) {
24167                     return v;
24168                 }
24169                 if (df) {
24170                     if (df == 'timestamp') {
24171                         return new Date(v*1000);
24172                     }
24173                     if (df == 'time') {
24174                         return new Date(parseInt(v, 10));
24175                     }
24176                     return Ext.Date.parse(v, df);
24177                 }
24178
24179                 parsed = Date.parse(v);
24180                 return parsed ? new Date(parsed) : null;
24181             },
24182             sortType: st.asDate,
24183             type: 'date'
24184         }
24185     });
24186
24187     Ext.apply(Ext.data.Types, {
24188         
24189         BOOLEAN: this.BOOL,
24190
24191         
24192         INTEGER: this.INT,
24193
24194         
24195         NUMBER: this.FLOAT
24196     });
24197 });
24198
24199
24200 Ext.define('Ext.data.Field', {
24201     requires: ['Ext.data.Types', 'Ext.data.SortTypes'],
24202     alias: 'data.field',
24203     
24204     constructor : function(config) {
24205         if (Ext.isString(config)) {
24206             config = {name: config};
24207         }
24208         Ext.apply(this, config);
24209         
24210         var types = Ext.data.Types,
24211             st = this.sortType,
24212             t;
24213
24214         if (this.type) {
24215             if (Ext.isString(this.type)) {
24216                 this.type = types[this.type.toUpperCase()] || types.AUTO;
24217             }
24218         } else {
24219             this.type = types.AUTO;
24220         }
24221
24222         
24223         if (Ext.isString(st)) {
24224             this.sortType = Ext.data.SortTypes[st];
24225         } else if(Ext.isEmpty(st)) {
24226             this.sortType = this.type.sortType;
24227         }
24228
24229         if (!this.convert) {
24230             this.convert = this.type.convert;
24231         }
24232     },
24233     
24234     
24235     
24236     
24237     
24238     
24239
24240     
24241     dateFormat: null,
24242     
24243     
24244     useNull: false,
24245     
24246     
24247     defaultValue: "",
24248
24249     
24250     mapping: null,
24251
24252     
24253     sortType : null,
24254
24255     
24256     sortDir : "ASC",
24257
24258     
24259     allowBlank : true,
24260
24261     
24262     persist: true
24263 });
24264
24265
24266 Ext.define('Ext.util.AbstractMixedCollection', {
24267     requires: ['Ext.util.Filter'],
24268
24269     mixins: {
24270         observable: 'Ext.util.Observable'
24271     },
24272
24273     constructor: function(allowFunctions, keyFn) {
24274         var me = this;
24275
24276         me.items = [];
24277         me.map = {};
24278         me.keys = [];
24279         me.length = 0;
24280
24281         me.addEvents(
24282             
24283             'clear',
24284
24285             
24286             'add',
24287
24288             
24289             'replace',
24290
24291             
24292             'remove'
24293         );
24294
24295         me.allowFunctions = allowFunctions === true;
24296
24297         if (keyFn) {
24298             me.getKey = keyFn;
24299         }
24300
24301         me.mixins.observable.constructor.call(me);
24302     },
24303
24304     
24305     allowFunctions : false,
24306
24307     
24308     add : function(key, obj){
24309         var me = this,
24310             myObj = obj,
24311             myKey = key,
24312             old;
24313
24314         if (arguments.length == 1) {
24315             myObj = myKey;
24316             myKey = me.getKey(myObj);
24317         }
24318         if (typeof myKey != 'undefined' && myKey !== null) {
24319             old = me.map[myKey];
24320             if (typeof old != 'undefined') {
24321                 return me.replace(myKey, myObj);
24322             }
24323             me.map[myKey] = myObj;
24324         }
24325         me.length++;
24326         me.items.push(myObj);
24327         me.keys.push(myKey);
24328         me.fireEvent('add', me.length - 1, myObj, myKey);
24329         return myObj;
24330     },
24331
24332     
24333     getKey : function(o){
24334          return o.id;
24335     },
24336
24337     
24338     replace : function(key, o){
24339         var me = this,
24340             old,
24341             index;
24342
24343         if (arguments.length == 1) {
24344             o = arguments[0];
24345             key = me.getKey(o);
24346         }
24347         old = me.map[key];
24348         if (typeof key == 'undefined' || key === null || typeof old == 'undefined') {
24349              return me.add(key, o);
24350         }
24351         index = me.indexOfKey(key);
24352         me.items[index] = o;
24353         me.map[key] = o;
24354         me.fireEvent('replace', key, old, o);
24355         return o;
24356     },
24357
24358     
24359     addAll : function(objs){
24360         var me = this,
24361             i = 0,
24362             args,
24363             len,
24364             key;
24365
24366         if (arguments.length > 1 || Ext.isArray(objs)) {
24367             args = arguments.length > 1 ? arguments : objs;
24368             for (len = args.length; i < len; i++) {
24369                 me.add(args[i]);
24370             }
24371         } else {
24372             for (key in objs) {
24373                 if (objs.hasOwnProperty(key)) {
24374                     if (me.allowFunctions || typeof objs[key] != 'function') {
24375                         me.add(key, objs[key]);
24376                     }
24377                 }
24378             }
24379         }
24380     },
24381
24382     
24383     each : function(fn, scope){
24384         var items = [].concat(this.items), 
24385             i = 0,
24386             len = items.length,
24387             item;
24388
24389         for (; i < len; i++) {
24390             item = items[i];
24391             if (fn.call(scope || item, item, i, len) === false) {
24392                 break;
24393             }
24394         }
24395     },
24396
24397     
24398     eachKey : function(fn, scope){
24399         var keys = this.keys,
24400             items = this.items,
24401             i = 0,
24402             len = keys.length;
24403
24404         for (; i < len; i++) {
24405             fn.call(scope || window, keys[i], items[i], i, len);
24406         }
24407     },
24408
24409     
24410     findBy : function(fn, scope) {
24411         var keys = this.keys,
24412             items = this.items,
24413             i = 0,
24414             len = items.length;
24415
24416         for (; i < len; i++) {
24417             if (fn.call(scope || window, items[i], keys[i])) {
24418                 return items[i];
24419             }
24420         }
24421         return null;
24422     },
24423
24424     find : function() {
24425         if (Ext.isDefined(Ext.global.console)) {
24426             Ext.global.console.warn('Ext.util.MixedCollection: find has been deprecated. Use findBy instead.');
24427         }
24428         return this.findBy.apply(this, arguments);
24429     },
24430
24431     
24432     insert : function(index, key, obj){
24433         var me = this,
24434             myKey = key,
24435             myObj = obj;
24436
24437         if (arguments.length == 2) {
24438             myObj = myKey;
24439             myKey = me.getKey(myObj);
24440         }
24441         if (me.containsKey(myKey)) {
24442             me.suspendEvents();
24443             me.removeAtKey(myKey);
24444             me.resumeEvents();
24445         }
24446         if (index >= me.length) {
24447             return me.add(myKey, myObj);
24448         }
24449         me.length++;
24450         Ext.Array.splice(me.items, index, 0, myObj);
24451         if (typeof myKey != 'undefined' && myKey !== null) {
24452             me.map[myKey] = myObj;
24453         }
24454         Ext.Array.splice(me.keys, index, 0, myKey);
24455         me.fireEvent('add', index, myObj, myKey);
24456         return myObj;
24457     },
24458
24459     
24460     remove : function(o){
24461         return this.removeAt(this.indexOf(o));
24462     },
24463
24464     
24465     removeAll : function(items){
24466         Ext.each(items || [], function(item) {
24467             this.remove(item);
24468         }, this);
24469
24470         return this;
24471     },
24472
24473     
24474     removeAt : function(index){
24475         var me = this,
24476             o,
24477             key;
24478
24479         if (index < me.length && index >= 0) {
24480             me.length--;
24481             o = me.items[index];
24482             Ext.Array.erase(me.items, index, 1);
24483             key = me.keys[index];
24484             if (typeof key != 'undefined') {
24485                 delete me.map[key];
24486             }
24487             Ext.Array.erase(me.keys, index, 1);
24488             me.fireEvent('remove', o, key);
24489             return o;
24490         }
24491         return false;
24492     },
24493
24494     
24495     removeAtKey : function(key){
24496         return this.removeAt(this.indexOfKey(key));
24497     },
24498
24499     
24500     getCount : function(){
24501         return this.length;
24502     },
24503
24504     
24505     indexOf : function(o){
24506         return Ext.Array.indexOf(this.items, o);
24507     },
24508
24509     
24510     indexOfKey : function(key){
24511         return Ext.Array.indexOf(this.keys, key);
24512     },
24513
24514     
24515     get : function(key) {
24516         var me = this,
24517             mk = me.map[key],
24518             item = mk !== undefined ? mk : (typeof key == 'number') ? me.items[key] : undefined;
24519         return typeof item != 'function' || me.allowFunctions ? item : null; 
24520     },
24521
24522     
24523     getAt : function(index) {
24524         return this.items[index];
24525     },
24526
24527     
24528     getByKey : function(key) {
24529         return this.map[key];
24530     },
24531
24532     
24533     contains : function(o){
24534         return Ext.Array.contains(this.items, o);
24535     },
24536
24537     
24538     containsKey : function(key){
24539         return typeof this.map[key] != 'undefined';
24540     },
24541
24542     
24543     clear : function(){
24544         var me = this;
24545
24546         me.length = 0;
24547         me.items = [];
24548         me.keys = [];
24549         me.map = {};
24550         me.fireEvent('clear');
24551     },
24552
24553     
24554     first : function() {
24555         return this.items[0];
24556     },
24557
24558     
24559     last : function() {
24560         return this.items[this.length - 1];
24561     },
24562
24563     
24564     sum: function(property, root, start, end) {
24565         var values = this.extractValues(property, root),
24566             length = values.length,
24567             sum    = 0,
24568             i;
24569
24570         start = start || 0;
24571         end   = (end || end === 0) ? end : length - 1;
24572
24573         for (i = start; i <= end; i++) {
24574             sum += values[i];
24575         }
24576
24577         return sum;
24578     },
24579
24580     
24581     collect: function(property, root, allowNull) {
24582         var values = this.extractValues(property, root),
24583             length = values.length,
24584             hits   = {},
24585             unique = [],
24586             value, strValue, i;
24587
24588         for (i = 0; i < length; i++) {
24589             value = values[i];
24590             strValue = String(value);
24591
24592             if ((allowNull || !Ext.isEmpty(value)) && !hits[strValue]) {
24593                 hits[strValue] = true;
24594                 unique.push(value);
24595             }
24596         }
24597
24598         return unique;
24599     },
24600
24601     
24602     extractValues: function(property, root) {
24603         var values = this.items;
24604
24605         if (root) {
24606             values = Ext.Array.pluck(values, root);
24607         }
24608
24609         return Ext.Array.pluck(values, property);
24610     },
24611
24612     
24613     getRange : function(start, end){
24614         var me = this,
24615             items = me.items,
24616             range = [],
24617             i;
24618
24619         if (items.length < 1) {
24620             return range;
24621         }
24622
24623         start = start || 0;
24624         end = Math.min(typeof end == 'undefined' ? me.length - 1 : end, me.length - 1);
24625         if (start <= end) {
24626             for (i = start; i <= end; i++) {
24627                 range[range.length] = items[i];
24628             }
24629         } else {
24630             for (i = start; i >= end; i--) {
24631                 range[range.length] = items[i];
24632             }
24633         }
24634         return range;
24635     },
24636
24637     
24638     filter : function(property, value, anyMatch, caseSensitive) {
24639         var filters = [],
24640             filterFn;
24641
24642         
24643         if (Ext.isString(property)) {
24644             filters.push(Ext.create('Ext.util.Filter', {
24645                 property     : property,
24646                 value        : value,
24647                 anyMatch     : anyMatch,
24648                 caseSensitive: caseSensitive
24649             }));
24650         } else if (Ext.isArray(property) || property instanceof Ext.util.Filter) {
24651             filters = filters.concat(property);
24652         }
24653
24654         
24655         
24656         filterFn = function(record) {
24657             var isMatch = true,
24658                 length = filters.length,
24659                 i;
24660
24661             for (i = 0; i < length; i++) {
24662                 var filter = filters[i],
24663                     fn     = filter.filterFn,
24664                     scope  = filter.scope;
24665
24666                 isMatch = isMatch && fn.call(scope, record);
24667             }
24668
24669             return isMatch;
24670         };
24671
24672         return this.filterBy(filterFn);
24673     },
24674
24675     
24676     filterBy : function(fn, scope) {
24677         var me = this,
24678             newMC  = new this.self(),
24679             keys   = me.keys,
24680             items  = me.items,
24681             length = items.length,
24682             i;
24683
24684         newMC.getKey = me.getKey;
24685
24686         for (i = 0; i < length; i++) {
24687             if (fn.call(scope || me, items[i], keys[i])) {
24688                 newMC.add(keys[i], items[i]);
24689             }
24690         }
24691
24692         return newMC;
24693     },
24694
24695     
24696     findIndex : function(property, value, start, anyMatch, caseSensitive){
24697         if(Ext.isEmpty(value, false)){
24698             return -1;
24699         }
24700         value = this.createValueMatcher(value, anyMatch, caseSensitive);
24701         return this.findIndexBy(function(o){
24702             return o && value.test(o[property]);
24703         }, null, start);
24704     },
24705
24706     
24707     findIndexBy : function(fn, scope, start){
24708         var me = this,
24709             keys = me.keys,
24710             items = me.items,
24711             i = start || 0,
24712             len = items.length;
24713
24714         for (; i < len; i++) {
24715             if (fn.call(scope || me, items[i], keys[i])) {
24716                 return i;
24717             }
24718         }
24719         return -1;
24720     },
24721
24722     
24723     createValueMatcher : function(value, anyMatch, caseSensitive, exactMatch) {
24724         if (!value.exec) { 
24725             var er = Ext.String.escapeRegex;
24726             value = String(value);
24727
24728             if (anyMatch === true) {
24729                 value = er(value);
24730             } else {
24731                 value = '^' + er(value);
24732                 if (exactMatch === true) {
24733                     value += '$';
24734                 }
24735             }
24736             value = new RegExp(value, caseSensitive ? '' : 'i');
24737         }
24738         return value;
24739     },
24740
24741     
24742     clone : function() {
24743         var me = this,
24744             copy = new this.self(),
24745             keys = me.keys,
24746             items = me.items,
24747             i = 0,
24748             len = items.length;
24749
24750         for(; i < len; i++){
24751             copy.add(keys[i], items[i]);
24752         }
24753         copy.getKey = me.getKey;
24754         return copy;
24755     }
24756 });
24757
24758
24759 Ext.define("Ext.util.Sortable", {
24760     
24761     isSortable: true,
24762
24763     
24764     defaultSortDirection: "ASC",
24765
24766     requires: [
24767         'Ext.util.Sorter'
24768     ],
24769
24770     
24771
24772     
24773     initSortable: function() {
24774         var me = this,
24775             sorters = me.sorters;
24776
24777         
24778         me.sorters = Ext.create('Ext.util.AbstractMixedCollection', false, function(item) {
24779             return item.id || item.property;
24780         });
24781
24782         if (sorters) {
24783             me.sorters.addAll(me.decodeSorters(sorters));
24784         }
24785     },
24786
24787     
24788     sort: function(sorters, direction, where, doSort) {
24789         var me = this,
24790             sorter, sorterFn,
24791             newSorters;
24792
24793         if (Ext.isArray(sorters)) {
24794             doSort = where;
24795             where = direction;
24796             newSorters = sorters;
24797         }
24798         else if (Ext.isObject(sorters)) {
24799             doSort = where;
24800             where = direction;
24801             newSorters = [sorters];
24802         }
24803         else if (Ext.isString(sorters)) {
24804             sorter = me.sorters.get(sorters);
24805
24806             if (!sorter) {
24807                 sorter = {
24808                     property : sorters,
24809                     direction: direction
24810                 };
24811                 newSorters = [sorter];
24812             }
24813             else if (direction === undefined) {
24814                 sorter.toggle();
24815             }
24816             else {
24817                 sorter.setDirection(direction);
24818             }
24819         }
24820
24821         if (newSorters && newSorters.length) {
24822             newSorters = me.decodeSorters(newSorters);
24823             if (Ext.isString(where)) {
24824                 if (where === 'prepend') {
24825                     sorters = me.sorters.clone().items;
24826
24827                     me.sorters.clear();
24828                     me.sorters.addAll(newSorters);
24829                     me.sorters.addAll(sorters);
24830                 }
24831                 else {
24832                     me.sorters.addAll(newSorters);
24833                 }
24834             }
24835             else {
24836                 me.sorters.clear();
24837                 me.sorters.addAll(newSorters);
24838             }
24839         }
24840
24841         if (doSort !== false) {
24842             me.onBeforeSort(newSorters);
24843             
24844             sorters = me.sorters.items;
24845             if (sorters.length) {
24846                 
24847                 sorterFn = function(r1, r2) {
24848                     var result = sorters[0].sort(r1, r2),
24849                         length = sorters.length,
24850                         i;
24851
24852                         
24853                         for (i = 1; i < length; i++) {
24854                             result = result || sorters[i].sort.call(this, r1, r2);
24855                         }
24856
24857                     return result;
24858                 };
24859
24860                 me.doSort(sorterFn);
24861             }
24862         }
24863
24864         return sorters;
24865     },
24866
24867     onBeforeSort: Ext.emptyFn,
24868
24869     
24870     decodeSorters: function(sorters) {
24871         if (!Ext.isArray(sorters)) {
24872             if (sorters === undefined) {
24873                 sorters = [];
24874             } else {
24875                 sorters = [sorters];
24876             }
24877         }
24878
24879         var length = sorters.length,
24880             Sorter = Ext.util.Sorter,
24881             fields = this.model ? this.model.prototype.fields : null,
24882             field,
24883             config, i;
24884
24885         for (i = 0; i < length; i++) {
24886             config = sorters[i];
24887
24888             if (!(config instanceof Sorter)) {
24889                 if (Ext.isString(config)) {
24890                     config = {
24891                         property: config
24892                     };
24893                 }
24894
24895                 Ext.applyIf(config, {
24896                     root     : this.sortRoot,
24897                     direction: "ASC"
24898                 });
24899
24900                 
24901                 if (config.fn) {
24902                     config.sorterFn = config.fn;
24903                 }
24904
24905                 
24906                 if (typeof config == 'function') {
24907                     config = {
24908                         sorterFn: config
24909                     };
24910                 }
24911
24912                 
24913                 if (fields && !config.transform) {
24914                     field = fields.get(config.property);
24915                     config.transform = field ? field.sortType : undefined;
24916                 }
24917                 sorters[i] = Ext.create('Ext.util.Sorter', config);
24918             }
24919         }
24920
24921         return sorters;
24922     },
24923
24924     getSorters: function() {
24925         return this.sorters.items;
24926     }
24927 });
24928
24929 Ext.define('Ext.util.MixedCollection', {
24930     extend: 'Ext.util.AbstractMixedCollection',
24931     mixins: {
24932         sortable: 'Ext.util.Sortable'
24933     },
24934
24935     
24936     constructor: function() {
24937         var me = this;
24938         me.callParent(arguments);
24939         me.addEvents('sort');
24940         me.mixins.sortable.initSortable.call(me);
24941     },
24942
24943     doSort: function(sorterFn) {
24944         this.sortBy(sorterFn);
24945     },
24946
24947     
24948     _sort : function(property, dir, fn){
24949         var me = this,
24950             i, len,
24951             dsc   = String(dir).toUpperCase() == 'DESC' ? -1 : 1,
24952
24953             
24954             c     = [],
24955             keys  = me.keys,
24956             items = me.items;
24957
24958         
24959         fn = fn || function(a, b) {
24960             return a - b;
24961         };
24962
24963         
24964         for(i = 0, len = items.length; i < len; i++){
24965             c[c.length] = {
24966                 key  : keys[i],
24967                 value: items[i],
24968                 index: i
24969             };
24970         }
24971
24972         
24973         Ext.Array.sort(c, function(a, b){
24974             var v = fn(a[property], b[property]) * dsc;
24975             if(v === 0){
24976                 v = (a.index < b.index ? -1 : 1);
24977             }
24978             return v;
24979         });
24980
24981         
24982         for(i = 0, len = c.length; i < len; i++){
24983             items[i] = c[i].value;
24984             keys[i]  = c[i].key;
24985         }
24986
24987         me.fireEvent('sort', me);
24988     },
24989
24990     
24991     sortBy: function(sorterFn) {
24992         var me     = this,
24993             items  = me.items,
24994             keys   = me.keys,
24995             length = items.length,
24996             temp   = [],
24997             i;
24998
24999         
25000         for (i = 0; i < length; i++) {
25001             temp[i] = {
25002                 key  : keys[i],
25003                 value: items[i],
25004                 index: i
25005             };
25006         }
25007
25008         Ext.Array.sort(temp, function(a, b) {
25009             var v = sorterFn(a.value, b.value);
25010             if (v === 0) {
25011                 v = (a.index < b.index ? -1 : 1);
25012             }
25013
25014             return v;
25015         });
25016
25017         
25018         for (i = 0; i < length; i++) {
25019             items[i] = temp[i].value;
25020             keys[i]  = temp[i].key;
25021         }
25022         
25023         me.fireEvent('sort', me, items, keys);
25024     },
25025
25026     
25027     reorder: function(mapping) {
25028         var me = this,
25029             items = me.items,
25030             index = 0,
25031             length = items.length,
25032             order = [],
25033             remaining = [],
25034             oldIndex;
25035
25036         me.suspendEvents();
25037
25038         
25039         for (oldIndex in mapping) {
25040             order[mapping[oldIndex]] = items[oldIndex];
25041         }
25042
25043         for (index = 0; index < length; index++) {
25044             if (mapping[index] == undefined) {
25045                 remaining.push(items[index]);
25046             }
25047         }
25048
25049         for (index = 0; index < length; index++) {
25050             if (order[index] == undefined) {
25051                 order[index] = remaining.shift();
25052             }
25053         }
25054
25055         me.clear();
25056         me.addAll(order);
25057
25058         me.resumeEvents();
25059         me.fireEvent('sort', me);
25060     },
25061
25062     
25063     sortByKey : function(dir, fn){
25064         this._sort('key', dir, fn || function(a, b){
25065             var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();
25066             return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
25067         });
25068     }
25069 });
25070
25071
25072 Ext.define('Ext.data.Errors', {
25073     extend: 'Ext.util.MixedCollection',
25074
25075     
25076     isValid: function() {
25077         return this.length === 0;
25078     },
25079
25080     
25081     getByField: function(fieldName) {
25082         var errors = [],
25083             error, field, i;
25084
25085         for (i = 0; i < this.length; i++) {
25086             error = this.items[i];
25087
25088             if (error.field == fieldName) {
25089                 errors.push(error);
25090             }
25091         }
25092
25093         return errors;
25094     }
25095 });
25096
25097
25098 Ext.define('Ext.data.reader.Reader', {
25099     requires: ['Ext.data.ResultSet'],
25100     alternateClassName: ['Ext.data.Reader', 'Ext.data.DataReader'],
25101     
25102     
25103
25104     
25105     totalProperty: 'total',
25106
25107     
25108     successProperty: 'success',
25109
25110     
25111     root: '',
25112     
25113     
25114     
25115     
25116     implicitIncludes: true,
25117     
25118     isReader: true,
25119     
25120     
25121     constructor: function(config) {
25122         var me = this;
25123         
25124         Ext.apply(me, config || {});
25125         me.fieldCount = 0;
25126         me.model = Ext.ModelManager.getModel(config.model);
25127         if (me.model) {
25128             me.buildExtractors();
25129         }
25130     },
25131
25132     
25133     setModel: function(model, setOnProxy) {
25134         var me = this;
25135         
25136         me.model = Ext.ModelManager.getModel(model);
25137         me.buildExtractors(true);
25138         
25139         if (setOnProxy && me.proxy) {
25140             me.proxy.setModel(me.model, true);
25141         }
25142     },
25143
25144     
25145     read: function(response) {
25146         var data = response;
25147         
25148         if (response && response.responseText) {
25149             data = this.getResponseData(response);
25150         }
25151         
25152         if (data) {
25153             return this.readRecords(data);
25154         } else {
25155             return this.nullResultSet;
25156         }
25157     },
25158
25159     
25160     readRecords: function(data) {
25161         var me  = this;
25162         
25163         
25164         if (me.fieldCount !== me.getFields().length) {
25165             me.buildExtractors(true);
25166         }
25167         
25168         
25169         me.rawData = data;
25170
25171         data = me.getData(data);
25172
25173         
25174         
25175         var root    = Ext.isArray(data) ? data : me.getRoot(data),
25176             success = true,
25177             recordCount = 0,
25178             total, value, records, message;
25179             
25180         if (root) {
25181             total = root.length;
25182         }
25183
25184         if (me.totalProperty) {
25185             value = parseInt(me.getTotal(data), 10);
25186             if (!isNaN(value)) {
25187                 total = value;
25188             }
25189         }
25190
25191         if (me.successProperty) {
25192             value = me.getSuccess(data);
25193             if (value === false || value === 'false') {
25194                 success = false;
25195             }
25196         }
25197         
25198         if (me.messageProperty) {
25199             message = me.getMessage(data);
25200         }
25201         
25202         if (root) {
25203             records = me.extractData(root);
25204             recordCount = records.length;
25205         } else {
25206             recordCount = 0;
25207             records = [];
25208         }
25209
25210         return Ext.create('Ext.data.ResultSet', {
25211             total  : total || recordCount,
25212             count  : recordCount,
25213             records: records,
25214             success: success,
25215             message: message
25216         });
25217     },
25218
25219     
25220     extractData : function(root) {
25221         var me = this,
25222             values  = [],
25223             records = [],
25224             Model   = me.model,
25225             i       = 0,
25226             length  = root.length,
25227             idProp  = me.getIdProperty(),
25228             node, id, record;
25229             
25230         if (!root.length && Ext.isObject(root)) {
25231             root = [root];
25232             length = 1;
25233         }
25234
25235         for (; i < length; i++) {
25236             node   = root[i];
25237             values = me.extractValues(node);
25238             id     = me.getId(node);
25239
25240             
25241             record = new Model(values, id, node);
25242             records.push(record);
25243                 
25244             if (me.implicitIncludes) {
25245                 me.readAssociated(record, node);
25246             }
25247         }
25248
25249         return records;
25250     },
25251     
25252     
25253     readAssociated: function(record, data) {
25254         var associations = record.associations.items,
25255             i            = 0,
25256             length       = associations.length,
25257             association, associationData, proxy, reader;
25258         
25259         for (; i < length; i++) {
25260             association     = associations[i];
25261             associationData = this.getAssociatedDataRoot(data, association.associationKey || association.name);
25262             
25263             if (associationData) {
25264                 reader = association.getReader();
25265                 if (!reader) {
25266                     proxy = association.associatedModel.proxy;
25267                     
25268                     if (proxy) {
25269                         reader = proxy.getReader();
25270                     } else {
25271                         reader = new this.constructor({
25272                             model: association.associatedName
25273                         });
25274                     }
25275                 }
25276                 association.read(record, reader, associationData);
25277             }  
25278         }
25279     },
25280     
25281     
25282     getAssociatedDataRoot: function(data, associationName) {
25283         return data[associationName];
25284     },
25285     
25286     getFields: function() {
25287         return this.model.prototype.fields.items;
25288     },
25289
25290     
25291     extractValues: function(data) {
25292         var fields = this.getFields(),
25293             i      = 0,
25294             length = fields.length,
25295             output = {},
25296             field, value;
25297
25298         for (; i < length; i++) {
25299             field = fields[i];
25300             value = this.extractorFunctions[i](data);
25301
25302             output[field.name] = value;
25303         }
25304
25305         return output;
25306     },
25307
25308     
25309     getData: function(data) {
25310         return data;
25311     },
25312
25313     
25314     getRoot: function(data) {
25315         return data;
25316     },
25317
25318     
25319     getResponseData: function(response) {
25320     },
25321
25322     
25323     onMetaChange : function(meta) {
25324         var fields = meta.fields,
25325             newModel;
25326         
25327         Ext.apply(this, meta);
25328         
25329         if (fields) {
25330             newModel = Ext.define("Ext.data.reader.Json-Model" + Ext.id(), {
25331                 extend: 'Ext.data.Model',
25332                 fields: fields
25333             });
25334             this.setModel(newModel, true);
25335         } else {
25336             this.buildExtractors(true);
25337         }
25338     },
25339     
25340     
25341     getIdProperty: function(){
25342         var prop = this.idProperty;
25343         if (Ext.isEmpty(prop)) {
25344             prop = this.model.prototype.idProperty;
25345         }
25346         return prop;
25347     },
25348
25349     
25350     buildExtractors: function(force) {
25351         var me          = this,
25352             idProp      = me.getIdProperty(),
25353             totalProp   = me.totalProperty,
25354             successProp = me.successProperty,
25355             messageProp = me.messageProperty,
25356             accessor;
25357             
25358         if (force === true) {
25359             delete me.extractorFunctions;
25360         }
25361         
25362         if (me.extractorFunctions) {
25363             return;
25364         }   
25365
25366         
25367         if (totalProp) {
25368             me.getTotal = me.createAccessor(totalProp);
25369         }
25370
25371         if (successProp) {
25372             me.getSuccess = me.createAccessor(successProp);
25373         }
25374
25375         if (messageProp) {
25376             me.getMessage = me.createAccessor(messageProp);
25377         }
25378
25379         if (idProp) {
25380             accessor = me.createAccessor(idProp);
25381
25382             me.getId = function(record) {
25383                 var id = accessor.call(me, record);
25384                 return (id === undefined || id === '') ? null : id;
25385             };
25386         } else {
25387             me.getId = function() {
25388                 return null;
25389             };
25390         }
25391         me.buildFieldExtractors();
25392     },
25393
25394     
25395     buildFieldExtractors: function() {
25396         
25397         var me = this,
25398             fields = me.getFields(),
25399             ln = fields.length,
25400             i  = 0,
25401             extractorFunctions = [],
25402             field, map;
25403
25404         for (; i < ln; i++) {
25405             field = fields[i];
25406             map   = (field.mapping !== undefined && field.mapping !== null) ? field.mapping : field.name;
25407
25408             extractorFunctions.push(me.createAccessor(map));
25409         }
25410         me.fieldCount = ln;
25411
25412         me.extractorFunctions = extractorFunctions;
25413     }
25414 }, function() {
25415     Ext.apply(this, {
25416         
25417         nullResultSet: Ext.create('Ext.data.ResultSet', {
25418             total  : 0,
25419             count  : 0,
25420             records: [],
25421             success: true
25422         })
25423     });
25424 });
25425
25426 Ext.define('Ext.data.reader.Json', {
25427     extend: 'Ext.data.reader.Reader',
25428     alternateClassName: 'Ext.data.JsonReader',
25429     alias : 'reader.json',
25430
25431     root: '',
25432
25433     
25434
25435     
25436     useSimpleAccessors: false,
25437
25438     
25439     readRecords: function(data) {
25440         
25441         if (data.metaData) {
25442             this.onMetaChange(data.metaData);
25443         }
25444
25445         
25446         this.jsonData = data;
25447         return this.callParent([data]);
25448     },
25449
25450     
25451     getResponseData: function(response) {
25452         var data;
25453         try {
25454             data = Ext.decode(response.responseText);
25455         }
25456         catch (ex) {
25457             Ext.Error.raise({
25458                 response: response,
25459                 json: response.responseText,
25460                 parseError: ex,
25461                 msg: 'Unable to parse the JSON returned by the server: ' + ex.toString()
25462             });
25463         }
25464
25465         return data;
25466     },
25467
25468     
25469     buildExtractors : function() {
25470         var me = this;
25471
25472         me.callParent(arguments);
25473
25474         if (me.root) {
25475             me.getRoot = me.createAccessor(me.root);
25476         } else {
25477             me.getRoot = function(root) {
25478                 return root;
25479             };
25480         }
25481     },
25482
25483     
25484     extractData: function(root) {
25485         var recordName = this.record,
25486             data = [],
25487             length, i;
25488
25489         if (recordName) {
25490             length = root.length;
25491             
25492             if (!length && Ext.isObject(root)) {
25493                 length = 1;
25494                 root = [root];
25495             }
25496
25497             for (i = 0; i < length; i++) {
25498                 data[i] = root[i][recordName];
25499             }
25500         } else {
25501             data = root;
25502         }
25503         return this.callParent([data]);
25504     },
25505
25506     
25507     createAccessor: function() {
25508         var re = /[\[\.]/;
25509
25510         return function(expr) {
25511             if (Ext.isEmpty(expr)) {
25512                 return Ext.emptyFn;
25513             }
25514             if (Ext.isFunction(expr)) {
25515                 return expr;
25516             }
25517             if (this.useSimpleAccessors !== true) {
25518                 var i = String(expr).search(re);
25519                 if (i >= 0) {
25520                     return Ext.functionFactory('obj', 'return obj' + (i > 0 ? '.' : '') + expr);
25521                 }
25522             }
25523             return function(obj) {
25524                 return obj[expr];
25525             };
25526         };
25527     }()
25528 });
25529
25530 Ext.define('Ext.data.writer.Json', {
25531     extend: 'Ext.data.writer.Writer',
25532     alternateClassName: 'Ext.data.JsonWriter',
25533     alias: 'writer.json',
25534     
25535     
25536     root: undefined,
25537     
25538     
25539     encode: false,
25540     
25541     
25542     allowSingle: true,
25543     
25544     
25545     writeRecords: function(request, data) {
25546         var root = this.root;
25547         
25548         if (this.allowSingle && data.length == 1) {
25549             
25550             data = data[0];
25551         }
25552         
25553         if (this.encode) {
25554             if (root) {
25555                 
25556                 request.params[root] = Ext.encode(data);
25557             } else {
25558             }
25559         } else {
25560             
25561             request.jsonData = request.jsonData || {};
25562             if (root) {
25563                 request.jsonData[root] = data;
25564             } else {
25565                 request.jsonData = data;
25566             }
25567         }
25568         return request;
25569     }
25570 });
25571
25572
25573 Ext.define('Ext.data.proxy.Proxy', {
25574     alias: 'proxy.proxy',
25575     alternateClassName: ['Ext.data.DataProxy', 'Ext.data.Proxy'],
25576     requires: [
25577         'Ext.data.reader.Json',
25578         'Ext.data.writer.Json'
25579     ],
25580     uses: [
25581         'Ext.data.Batch', 
25582         'Ext.data.Operation', 
25583         'Ext.data.Model'
25584     ],
25585     mixins: {
25586         observable: 'Ext.util.Observable'
25587     },
25588     
25589     
25590     batchOrder: 'create,update,destroy',
25591     
25592     
25593     batchActions: true,
25594     
25595     
25596     defaultReaderType: 'json',
25597     
25598     
25599     defaultWriterType: 'json',
25600     
25601     
25602     
25603     
25604     
25605     
25606     
25607     isProxy: true,
25608     
25609     
25610     constructor: function(config) {
25611         config = config || {};
25612         
25613         if (config.model === undefined) {
25614             delete config.model;
25615         }
25616
25617         this.mixins.observable.constructor.call(this, config);
25618         
25619         if (this.model !== undefined && !(this.model instanceof Ext.data.Model)) {
25620             this.setModel(this.model);
25621         }
25622     },
25623     
25624     
25625     setModel: function(model, setOnStore) {
25626         this.model = Ext.ModelManager.getModel(model);
25627         
25628         var reader = this.reader,
25629             writer = this.writer;
25630         
25631         this.setReader(reader);
25632         this.setWriter(writer);
25633         
25634         if (setOnStore && this.store) {
25635             this.store.setModel(this.model);
25636         }
25637     },
25638     
25639     
25640     getModel: function() {
25641         return this.model;
25642     },
25643     
25644     
25645     setReader: function(reader) {
25646         var me = this;
25647         
25648         if (reader === undefined || typeof reader == 'string') {
25649             reader = {
25650                 type: reader
25651             };
25652         }
25653
25654         if (reader.isReader) {
25655             reader.setModel(me.model);
25656         } else {
25657             Ext.applyIf(reader, {
25658                 proxy: me,
25659                 model: me.model,
25660                 type : me.defaultReaderType
25661             });
25662
25663             reader = Ext.createByAlias('reader.' + reader.type, reader);
25664         }
25665         
25666         me.reader = reader;
25667         return me.reader;
25668     },
25669     
25670     
25671     getReader: function() {
25672         return this.reader;
25673     },
25674     
25675     
25676     setWriter: function(writer) {
25677         if (writer === undefined || typeof writer == 'string') {
25678             writer = {
25679                 type: writer
25680             };
25681         }
25682
25683         if (!(writer instanceof Ext.data.writer.Writer)) {
25684             Ext.applyIf(writer, {
25685                 model: this.model,
25686                 type : this.defaultWriterType
25687             });
25688
25689             writer = Ext.createByAlias('writer.' + writer.type, writer);
25690         }
25691         
25692         this.writer = writer;
25693         
25694         return this.writer;
25695     },
25696     
25697     
25698     getWriter: function() {
25699         return this.writer;
25700     },
25701     
25702     
25703     create: Ext.emptyFn,
25704     
25705     
25706     read: Ext.emptyFn,
25707     
25708     
25709     update: Ext.emptyFn,
25710     
25711     
25712     destroy: Ext.emptyFn,
25713     
25714     
25715     batch: function(operations, listeners) {
25716         var me = this,
25717             batch = Ext.create('Ext.data.Batch', {
25718                 proxy: me,
25719                 listeners: listeners || {}
25720             }),
25721             useBatch = me.batchActions, 
25722             records;
25723         
25724         Ext.each(me.batchOrder.split(','), function(action) {
25725             records = operations[action];
25726             if (records) {
25727                 if (useBatch) {
25728                     batch.add(Ext.create('Ext.data.Operation', {
25729                         action: action,
25730                         records: records
25731                     }));
25732                 } else {
25733                     Ext.each(records, function(record){
25734                         batch.add(Ext.create('Ext.data.Operation', {
25735                             action : action, 
25736                             records: [record]
25737                         }));
25738                     });
25739                 }
25740             }
25741         }, me);
25742         
25743         batch.start();
25744         return batch;
25745     }
25746 }, function() {
25747     
25748     
25749     
25750     Ext.data.DataProxy = this;
25751     
25752     
25753     
25754 });
25755
25756
25757 Ext.define('Ext.data.proxy.Server', {
25758     extend: 'Ext.data.proxy.Proxy',
25759     alias : 'proxy.server',
25760     alternateClassName: 'Ext.data.ServerProxy',
25761     uses  : ['Ext.data.Request'],
25762
25763     
25764
25765     
25766     pageParam: 'page',
25767
25768     
25769     startParam: 'start',
25770
25771     
25772     limitParam: 'limit',
25773
25774     
25775     groupParam: 'group',
25776
25777     
25778     sortParam: 'sort',
25779
25780     
25781     filterParam: 'filter',
25782
25783     
25784     directionParam: 'dir',
25785
25786     
25787     simpleSortMode: false,
25788
25789     
25790     noCache : true,
25791
25792     
25793     cacheString: "_dc",
25794
25795     
25796     timeout : 30000,
25797
25798     
25799
25800     constructor: function(config) {
25801         var me = this;
25802
25803         config = config || {};
25804         this.addEvents(
25805             
25806             'exception'
25807         );
25808         me.callParent([config]);
25809
25810         
25811         me.extraParams = config.extraParams || {};
25812
25813         me.api = config.api || {};
25814
25815         
25816         me.nocache = me.noCache;
25817     },
25818
25819     
25820     create: function() {
25821         return this.doRequest.apply(this, arguments);
25822     },
25823
25824     read: function() {
25825         return this.doRequest.apply(this, arguments);
25826     },
25827
25828     update: function() {
25829         return this.doRequest.apply(this, arguments);
25830     },
25831
25832     destroy: function() {
25833         return this.doRequest.apply(this, arguments);
25834     },
25835
25836     
25837     buildRequest: function(operation) {
25838         var params = Ext.applyIf(operation.params || {}, this.extraParams || {}),
25839             request;
25840
25841         
25842         params = Ext.applyIf(params, this.getParams(operation));
25843
25844         if (operation.id && !params.id) {
25845             params.id = operation.id;
25846         }
25847
25848         request = Ext.create('Ext.data.Request', {
25849             params   : params,
25850             action   : operation.action,
25851             records  : operation.records,
25852             operation: operation,
25853             url      : operation.url
25854         });
25855
25856         request.url = this.buildUrl(request);
25857
25858         
25859         operation.request = request;
25860
25861         return request;
25862     },
25863
25864     
25865     processResponse: function(success, operation, request, response, callback, scope){
25866         var me = this,
25867             reader,
25868             result;
25869
25870         if (success === true) {
25871             reader = me.getReader();
25872             result = reader.read(me.extractResponseData(response));
25873
25874             if (result.success !== false) {
25875                 
25876                 Ext.apply(operation, {
25877                     response: response,
25878                     resultSet: result
25879                 });
25880
25881                 operation.commitRecords(result.records);
25882                 operation.setCompleted();
25883                 operation.setSuccessful();
25884             } else {
25885                 operation.setException(result.message);
25886                 me.fireEvent('exception', this, response, operation);
25887             }
25888         } else {
25889             me.setException(operation, response);
25890             me.fireEvent('exception', this, response, operation);
25891         }
25892
25893         
25894         if (typeof callback == 'function') {
25895             callback.call(scope || me, operation);
25896         }
25897
25898         me.afterRequest(request, success);
25899     },
25900
25901     
25902     setException: function(operation, response){
25903         operation.setException({
25904             status: response.status,
25905             statusText: response.statusText
25906         });
25907     },
25908
25909     
25910     extractResponseData: function(response){
25911         return response;
25912     },
25913
25914     
25915     applyEncoding: function(value){
25916         return Ext.encode(value);
25917     },
25918
25919     
25920     encodeSorters: function(sorters) {
25921         var min = [],
25922             length = sorters.length,
25923             i = 0;
25924
25925         for (; i < length; i++) {
25926             min[i] = {
25927                 property : sorters[i].property,
25928                 direction: sorters[i].direction
25929             };
25930         }
25931         return this.applyEncoding(min);
25932
25933     },
25934
25935     
25936     encodeFilters: function(filters) {
25937         var min = [],
25938             length = filters.length,
25939             i = 0;
25940
25941         for (; i < length; i++) {
25942             min[i] = {
25943                 property: filters[i].property,
25944                 value   : filters[i].value
25945             };
25946         }
25947         return this.applyEncoding(min);
25948     },
25949
25950     
25951     getParams: function(operation) {
25952         var me             = this,
25953             params         = {},
25954             isDef          = Ext.isDefined,
25955             groupers       = operation.groupers,
25956             sorters        = operation.sorters,
25957             filters        = operation.filters,
25958             page           = operation.page,
25959             start          = operation.start,
25960             limit          = operation.limit,
25961
25962             simpleSortMode = me.simpleSortMode,
25963
25964             pageParam      = me.pageParam,
25965             startParam     = me.startParam,
25966             limitParam     = me.limitParam,
25967             groupParam     = me.groupParam,
25968             sortParam      = me.sortParam,
25969             filterParam    = me.filterParam,
25970             directionParam = me.directionParam;
25971
25972         if (pageParam && isDef(page)) {
25973             params[pageParam] = page;
25974         }
25975
25976         if (startParam && isDef(start)) {
25977             params[startParam] = start;
25978         }
25979
25980         if (limitParam && isDef(limit)) {
25981             params[limitParam] = limit;
25982         }
25983
25984         if (groupParam && groupers && groupers.length > 0) {
25985             
25986             params[groupParam] = me.encodeSorters(groupers);
25987         }
25988
25989         if (sortParam && sorters && sorters.length > 0) {
25990             if (simpleSortMode) {
25991                 params[sortParam] = sorters[0].property;
25992                 params[directionParam] = sorters[0].direction;
25993             } else {
25994                 params[sortParam] = me.encodeSorters(sorters);
25995             }
25996
25997         }
25998
25999         if (filterParam && filters && filters.length > 0) {
26000             params[filterParam] = me.encodeFilters(filters);
26001         }
26002
26003         return params;
26004     },
26005
26006     
26007     buildUrl: function(request) {
26008         var me = this,
26009             url = me.getUrl(request);
26010
26011
26012         if (me.noCache) {
26013             url = Ext.urlAppend(url, Ext.String.format("{0}={1}", me.cacheString, Ext.Date.now()));
26014         }
26015
26016         return url;
26017     },
26018
26019     
26020     getUrl: function(request){
26021         return request.url || this.api[request.action] || this.url;
26022     },
26023
26024     
26025     doRequest: function(operation, callback, scope) {
26026     },
26027
26028     
26029     afterRequest: Ext.emptyFn,
26030
26031     onDestroy: function() {
26032         Ext.destroy(this.reader, this.writer);
26033     }
26034 });
26035
26036
26037 Ext.define('Ext.data.proxy.Ajax', {
26038     requires: ['Ext.util.MixedCollection', 'Ext.Ajax'],
26039     extend: 'Ext.data.proxy.Server',
26040     alias: 'proxy.ajax',
26041     alternateClassName: ['Ext.data.HttpProxy', 'Ext.data.AjaxProxy'],
26042     
26043     
26044     actionMethods: {
26045         create : 'POST',
26046         read   : 'GET',
26047         update : 'POST',
26048         destroy: 'POST'
26049     },
26050     
26051     
26052     
26053     
26054     doRequest: function(operation, callback, scope) {
26055         var writer  = this.getWriter(),
26056             request = this.buildRequest(operation, callback, scope);
26057             
26058         if (operation.allowWrite()) {
26059             request = writer.write(request);
26060         }
26061         
26062         Ext.apply(request, {
26063             headers       : this.headers,
26064             timeout       : this.timeout,
26065             scope         : this,
26066             callback      : this.createRequestCallback(request, operation, callback, scope),
26067             method        : this.getMethod(request),
26068             disableCaching: false 
26069         });
26070         
26071         Ext.Ajax.request(request);
26072         
26073         return request;
26074     },
26075     
26076     
26077     getMethod: function(request) {
26078         return this.actionMethods[request.action];
26079     },
26080     
26081     
26082     createRequestCallback: function(request, operation, callback, scope) {
26083         var me = this;
26084         
26085         return function(options, success, response) {
26086             me.processResponse(success, operation, request, response, callback, scope);
26087         };
26088     }
26089 }, function() {
26090     
26091     Ext.data.HttpProxy = this;
26092 });
26093
26094
26095 Ext.define('Ext.data.Model', {
26096     alternateClassName: 'Ext.data.Record',
26097
26098     mixins: {
26099         observable: 'Ext.util.Observable'
26100     },
26101
26102     requires: [
26103         'Ext.ModelManager',
26104         'Ext.data.IdGenerator',
26105         'Ext.data.Field',
26106         'Ext.data.Errors',
26107         'Ext.data.Operation',
26108         'Ext.data.validations',
26109         'Ext.data.proxy.Ajax',
26110         'Ext.util.MixedCollection'
26111     ],
26112
26113     onClassExtended: function(cls, data) {
26114         var onBeforeClassCreated = data.onBeforeClassCreated;
26115
26116         data.onBeforeClassCreated = function(cls, data) {
26117             var me = this,
26118                 name = Ext.getClassName(cls),
26119                 prototype = cls.prototype,
26120                 superCls = cls.prototype.superclass,
26121
26122                 validations = data.validations || [],
26123                 fields = data.fields || [],
26124                 associations = data.associations || [],
26125                 belongsTo = data.belongsTo,
26126                 hasMany = data.hasMany,
26127                 idgen = data.idgen,
26128
26129                 fieldsMixedCollection = new Ext.util.MixedCollection(false, function(field) {
26130                     return field.name;
26131                 }),
26132
26133                 associationsMixedCollection = new Ext.util.MixedCollection(false, function(association) {
26134                     return association.name;
26135                 }),
26136
26137                 superValidations = superCls.validations,
26138                 superFields = superCls.fields,
26139                 superAssociations = superCls.associations,
26140
26141                 association, i, ln,
26142                 dependencies = [];
26143
26144             
26145             cls.modelName = name;
26146             prototype.modelName = name;
26147
26148             
26149             if (superValidations) {
26150                 validations = superValidations.concat(validations);
26151             }
26152
26153             data.validations = validations;
26154
26155             
26156             if (superFields) {
26157                 fields = superFields.items.concat(fields);
26158             }
26159
26160             for (i = 0, ln = fields.length; i < ln; ++i) {
26161                 fieldsMixedCollection.add(new Ext.data.Field(fields[i]));
26162             }
26163
26164             data.fields = fieldsMixedCollection;
26165
26166             if (idgen) {
26167                 data.idgen = Ext.data.IdGenerator.get(idgen);
26168             }
26169
26170             
26171             
26172             if (belongsTo) {
26173                 belongsTo = Ext.Array.from(belongsTo);
26174
26175                 for (i = 0, ln = belongsTo.length; i < ln; ++i) {
26176                     association = belongsTo[i];
26177
26178                     if (!Ext.isObject(association)) {
26179                         association = {model: association};
26180                     }
26181
26182                     association.type = 'belongsTo';
26183                     associations.push(association);
26184                 }
26185
26186                 delete data.belongsTo;
26187             }
26188
26189             if (hasMany) {
26190                 hasMany = Ext.Array.from(hasMany);
26191                 for (i = 0, ln = hasMany.length; i < ln; ++i) {
26192                     association = hasMany[i];
26193
26194                     if (!Ext.isObject(association)) {
26195                         association = {model: association};
26196                     }
26197
26198                     association.type = 'hasMany';
26199                     associations.push(association);
26200                 }
26201
26202                 delete data.hasMany;
26203             }
26204
26205             if (superAssociations) {
26206                 associations = superAssociations.items.concat(associations);
26207             }
26208
26209             for (i = 0, ln = associations.length; i < ln; ++i) {
26210                 dependencies.push('association.' + associations[i].type.toLowerCase());
26211             }
26212
26213             if (data.proxy) {
26214                 if (typeof data.proxy === 'string') {
26215                     dependencies.push('proxy.' + data.proxy);
26216                 }
26217                 else if (typeof data.proxy.type === 'string') {
26218                     dependencies.push('proxy.' + data.proxy.type);
26219                 }
26220             }
26221
26222             Ext.require(dependencies, function() {
26223                 Ext.ModelManager.registerType(name, cls);
26224
26225                 for (i = 0, ln = associations.length; i < ln; ++i) {
26226                     association = associations[i];
26227
26228                     Ext.apply(association, {
26229                         ownerModel: name,
26230                         associatedModel: association.model
26231                     });
26232
26233                     if (Ext.ModelManager.getModel(association.model) === undefined) {
26234                         Ext.ModelManager.registerDeferredAssociation(association);
26235                     } else {
26236                         associationsMixedCollection.add(Ext.data.Association.create(association));
26237                     }
26238                 }
26239
26240                 data.associations = associationsMixedCollection;
26241
26242                 onBeforeClassCreated.call(me, cls, data);
26243
26244                 cls.setProxy(cls.prototype.proxy || cls.prototype.defaultProxyType);
26245
26246                 
26247                 Ext.ModelManager.onModelDefined(cls);
26248             });
26249         };
26250     },
26251
26252     inheritableStatics: {
26253         
26254         setProxy: function(proxy) {
26255             
26256             if (!proxy.isProxy) {
26257                 if (typeof proxy == "string") {
26258                     proxy = {
26259                         type: proxy
26260                     };
26261                 }
26262                 proxy = Ext.createByAlias("proxy." + proxy.type, proxy);
26263             }
26264             proxy.setModel(this);
26265             this.proxy = this.prototype.proxy = proxy;
26266
26267             return proxy;
26268         },
26269
26270         
26271         getProxy: function() {
26272             return this.proxy;
26273         },
26274
26275         
26276         load: function(id, config) {
26277             config = Ext.apply({}, config);
26278             config = Ext.applyIf(config, {
26279                 action: 'read',
26280                 id    : id
26281             });
26282
26283             var operation  = Ext.create('Ext.data.Operation', config),
26284                 scope      = config.scope || this,
26285                 record     = null,
26286                 callback;
26287
26288             callback = function(operation) {
26289                 if (operation.wasSuccessful()) {
26290                     record = operation.getRecords()[0];
26291                     Ext.callback(config.success, scope, [record, operation]);
26292                 } else {
26293                     Ext.callback(config.failure, scope, [record, operation]);
26294                 }
26295                 Ext.callback(config.callback, scope, [record, operation]);
26296             };
26297
26298             this.proxy.read(operation, callback, this);
26299         }
26300     },
26301
26302     statics: {
26303         PREFIX : 'ext-record',
26304         AUTO_ID: 1,
26305         EDIT   : 'edit',
26306         REJECT : 'reject',
26307         COMMIT : 'commit',
26308
26309         
26310         id: function(rec) {
26311             var id = [this.PREFIX, '-', this.AUTO_ID++].join('');
26312             rec.phantom = true;
26313             rec.internalId = id;
26314             return id;
26315         }
26316     },
26317
26318     
26319     idgen: {
26320         isGenerator: true,
26321         type: 'default',
26322
26323         generate: function () {
26324             return null;
26325         },
26326         getRecId: function (rec) {
26327             return rec.modelName + '-' + rec.internalId;
26328         }
26329     },
26330
26331     
26332     editing : false,
26333
26334     
26335     dirty : false,
26336
26337     
26338     persistenceProperty: 'data',
26339
26340     evented: false,
26341     isModel: true,
26342
26343     
26344     phantom : false,
26345
26346     
26347     idProperty: 'id',
26348
26349     
26350     defaultProxyType: 'ajax',
26351
26352     
26353     
26354     
26355
26356     
26357
26358     
26359     
26360     
26361     
26362     
26363
26364     
26365
26366     
26367     constructor: function(data, id, raw) {
26368         data = data || {};
26369
26370         var me = this,
26371             fields,
26372             length,
26373             field,
26374             name,
26375             i,
26376             newId,
26377             isArray = Ext.isArray(data),
26378             newData = isArray ? {} : null; 
26379
26380         
26381         me.internalId = (id || id === 0) ? id : Ext.data.Model.id(me);
26382
26383         
26384         me.raw = raw;
26385
26386         Ext.applyIf(me, {
26387             data: {}
26388         });
26389
26390         
26391         me.modified = {};
26392
26393         
26394         if (me.persistanceProperty) {
26395             me.persistenceProperty = me.persistanceProperty;
26396         }
26397         me[me.persistenceProperty] = {};
26398
26399         me.mixins.observable.constructor.call(me);
26400
26401         
26402         fields = me.fields.items;
26403         length = fields.length;
26404
26405         for (i = 0; i < length; i++) {
26406             field = fields[i];
26407             name  = field.name;
26408
26409             if (isArray){
26410                 
26411                 
26412                 newData[name] = data[i];
26413             }
26414             else if (data[name] === undefined) {
26415                 data[name] = field.defaultValue;
26416             }
26417         }
26418
26419         me.set(newData || data);
26420
26421         if (me.getId()) {
26422             me.phantom = false;
26423         } else if (me.phantom) {
26424             newId = me.idgen.generate();
26425             if (newId !== null) {
26426                 me.setId(newId);
26427             }
26428         }
26429
26430         
26431         me.dirty = false;
26432         me.modified = {};
26433
26434         if (typeof me.init == 'function') {
26435             me.init();
26436         }
26437
26438         me.id = me.idgen.getRecId(me);
26439     },
26440
26441     
26442     get: function(field) {
26443         return this[this.persistenceProperty][field];
26444     },
26445
26446     
26447     set: function(fieldName, value) {
26448         var me = this,
26449             fields = me.fields,
26450             modified = me.modified,
26451             convertFields = [],
26452             field, key, i, currentValue, notEditing, count, length;
26453
26454         
26455         if (arguments.length == 1 && Ext.isObject(fieldName)) {
26456             notEditing = !me.editing;
26457             count = 0;
26458             for (key in fieldName) {
26459                 if (fieldName.hasOwnProperty(key)) {
26460
26461                     
26462                     
26463                     field = fields.get(key);
26464                     if (field && field.convert !== field.type.convert) {
26465                         convertFields.push(key);
26466                         continue;
26467                     }
26468
26469                     if (!count && notEditing) {
26470                         me.beginEdit();
26471                     }
26472                     ++count;
26473                     me.set(key, fieldName[key]);
26474                 }
26475             }
26476
26477             length = convertFields.length;
26478             if (length) {
26479                 if (!count && notEditing) {
26480                     me.beginEdit();
26481                 }
26482                 count += length;
26483                 for (i = 0; i < length; i++) {
26484                     field = convertFields[i];
26485                     me.set(field, fieldName[field]);
26486                 }
26487             }
26488
26489             if (notEditing && count) {
26490                 me.endEdit();
26491             }
26492         } else {
26493             if (fields) {
26494                 field = fields.get(fieldName);
26495
26496                 if (field && field.convert) {
26497                     value = field.convert(value, me);
26498                 }
26499             }
26500             currentValue = me.get(fieldName);
26501             me[me.persistenceProperty][fieldName] = value;
26502
26503             if (field && field.persist && !me.isEqual(currentValue, value)) {
26504                 if (me.isModified(fieldName)) {
26505                     if (me.isEqual(modified[fieldName], value)) {
26506                         
26507                         
26508                         delete modified[fieldName];
26509                         
26510                         
26511                         me.dirty = false;
26512                         for (key in modified) {
26513                             if (modified.hasOwnProperty(key)){
26514                                 me.dirty = true;
26515                                 break;
26516                             }
26517                         }
26518                     }
26519                 } else {
26520                     me.dirty = true;
26521                     modified[fieldName] = currentValue;
26522                 }
26523             }
26524
26525             if (!me.editing) {
26526                 me.afterEdit();
26527             }
26528         }
26529     },
26530
26531     
26532     isEqual: function(a, b){
26533         if (Ext.isDate(a) && Ext.isDate(b)) {
26534             return a.getTime() === b.getTime();
26535         }
26536         return a === b;
26537     },
26538
26539     
26540     beginEdit : function(){
26541         var me = this;
26542         if (!me.editing) {
26543             me.editing = true;
26544             me.dirtySave = me.dirty;
26545             me.dataSave = Ext.apply({}, me[me.persistenceProperty]);
26546             me.modifiedSave = Ext.apply({}, me.modified);
26547         }
26548     },
26549
26550     
26551     cancelEdit : function(){
26552         var me = this;
26553         if (me.editing) {
26554             me.editing = false;
26555             
26556             me.modified = me.modifiedSave;
26557             me[me.persistenceProperty] = me.dataSave;
26558             me.dirty = me.dirtySave;
26559             delete me.modifiedSave;
26560             delete me.dataSave;
26561             delete me.dirtySave;
26562         }
26563     },
26564
26565     
26566     endEdit : function(silent){
26567         var me = this,
26568             didChange;
26569             
26570         if (me.editing) {
26571             me.editing = false;
26572             didChange = me.dirty || me.changedWhileEditing();
26573             delete me.modifiedSave;
26574             delete me.dataSave;
26575             delete me.dirtySave;
26576             if (silent !== true && didChange) {
26577                 me.afterEdit();
26578             }
26579         }
26580     },
26581     
26582     
26583     changedWhileEditing: function(){
26584         var me = this,
26585             saved = me.dataSave,
26586             data = me[me.persistenceProperty],
26587             key;
26588             
26589         for (key in data) {
26590             if (data.hasOwnProperty(key)) {
26591                 if (!me.isEqual(data[key], saved[key])) {
26592                     return true;
26593                 }
26594             }
26595         }
26596         return false; 
26597     },
26598
26599     
26600     getChanges : function(){
26601         var modified = this.modified,
26602             changes  = {},
26603             field;
26604
26605         for (field in modified) {
26606             if (modified.hasOwnProperty(field)){
26607                 changes[field] = this.get(field);
26608             }
26609         }
26610
26611         return changes;
26612     },
26613
26614     
26615     isModified : function(fieldName) {
26616         return this.modified.hasOwnProperty(fieldName);
26617     },
26618
26619     
26620     setDirty : function() {
26621         var me = this,
26622             name;
26623
26624         me.dirty = true;
26625
26626         me.fields.each(function(field) {
26627             if (field.persist) {
26628                 name = field.name;
26629                 me.modified[name] = me.get(name);
26630             }
26631         }, me);
26632     },
26633
26634
26635     
26636     reject : function(silent) {
26637         var me = this,
26638             modified = me.modified,
26639             field;
26640
26641         for (field in modified) {
26642             if (modified.hasOwnProperty(field)) {
26643                 if (typeof modified[field] != "function") {
26644                     me[me.persistenceProperty][field] = modified[field];
26645                 }
26646             }
26647         }
26648
26649         me.dirty = false;
26650         me.editing = false;
26651         me.modified = {};
26652
26653         if (silent !== true) {
26654             me.afterReject();
26655         }
26656     },
26657
26658     
26659     commit : function(silent) {
26660         var me = this;
26661
26662         me.phantom = me.dirty = me.editing = false;
26663         me.modified = {};
26664
26665         if (silent !== true) {
26666             me.afterCommit();
26667         }
26668     },
26669
26670     
26671     copy : function(newId) {
26672         var me = this;
26673
26674         return new me.self(Ext.apply({}, me[me.persistenceProperty]), newId || me.internalId);
26675     },
26676
26677     
26678     setProxy: function(proxy) {
26679         
26680         if (!proxy.isProxy) {
26681             if (typeof proxy === "string") {
26682                 proxy = {
26683                     type: proxy
26684                 };
26685             }
26686             proxy = Ext.createByAlias("proxy." + proxy.type, proxy);
26687         }
26688         proxy.setModel(this.self);
26689         this.proxy = proxy;
26690
26691         return proxy;
26692     },
26693
26694     
26695     getProxy: function() {
26696         return this.proxy;
26697     },
26698
26699     
26700     validate: function() {
26701         var errors      = Ext.create('Ext.data.Errors'),
26702             validations = this.validations,
26703             validators  = Ext.data.validations,
26704             length, validation, field, valid, type, i;
26705
26706         if (validations) {
26707             length = validations.length;
26708
26709             for (i = 0; i < length; i++) {
26710                 validation = validations[i];
26711                 field = validation.field || validation.name;
26712                 type  = validation.type;
26713                 valid = validators[type](validation, this.get(field));
26714
26715                 if (!valid) {
26716                     errors.add({
26717                         field  : field,
26718                         message: validation.message || validators[type + 'Message']
26719                     });
26720                 }
26721             }
26722         }
26723
26724         return errors;
26725     },
26726
26727     
26728     isValid: function(){
26729         return this.validate().isValid();
26730     },
26731
26732     
26733     save: function(options) {
26734         options = Ext.apply({}, options);
26735
26736         var me     = this,
26737             action = me.phantom ? 'create' : 'update',
26738             record = null,
26739             scope  = options.scope || me,
26740             operation,
26741             callback;
26742
26743         Ext.apply(options, {
26744             records: [me],
26745             action : action
26746         });
26747
26748         operation = Ext.create('Ext.data.Operation', options);
26749
26750         callback = function(operation) {
26751             if (operation.wasSuccessful()) {
26752                 record = operation.getRecords()[0];
26753                 
26754                 
26755                 me.set(record.data);
26756                 record.dirty = false;
26757
26758                 Ext.callback(options.success, scope, [record, operation]);
26759             } else {
26760                 Ext.callback(options.failure, scope, [record, operation]);
26761             }
26762
26763             Ext.callback(options.callback, scope, [record, operation]);
26764         };
26765
26766         me.getProxy()[action](operation, callback, me);
26767
26768         return me;
26769     },
26770
26771     
26772     destroy: function(options){
26773         options = Ext.apply({}, options);
26774
26775         var me     = this,
26776             record = null,
26777             scope  = options.scope || me,
26778             operation,
26779             callback;
26780
26781         Ext.apply(options, {
26782             records: [me],
26783             action : 'destroy'
26784         });
26785
26786         operation = Ext.create('Ext.data.Operation', options);
26787         callback = function(operation) {
26788             if (operation.wasSuccessful()) {
26789                 Ext.callback(options.success, scope, [record, operation]);
26790             } else {
26791                 Ext.callback(options.failure, scope, [record, operation]);
26792             }
26793             Ext.callback(options.callback, scope, [record, operation]);
26794         };
26795
26796         me.getProxy().destroy(operation, callback, me);
26797         return me;
26798     },
26799
26800     
26801     getId: function() {
26802         return this.get(this.idProperty);
26803     },
26804
26805     
26806     setId: function(id) {
26807         this.set(this.idProperty, id);
26808     },
26809
26810     
26811     join : function(store) {
26812         
26813         this.store = store;
26814     },
26815
26816     
26817     unjoin: function(store) {
26818         delete this.store;
26819     },
26820
26821     
26822     afterEdit : function() {
26823         this.callStore('afterEdit');
26824     },
26825
26826     
26827     afterReject : function() {
26828         this.callStore("afterReject");
26829     },
26830
26831     
26832     afterCommit: function() {
26833         this.callStore('afterCommit');
26834     },
26835
26836     
26837     callStore: function(fn) {
26838         var store = this.store;
26839
26840         if (store !== undefined && typeof store[fn] == "function") {
26841             store[fn](this);
26842         }
26843     },
26844
26845     
26846     getAssociatedData: function(){
26847         return this.prepareAssociatedData(this, [], null);
26848     },
26849
26850     
26851     prepareAssociatedData: function(record, ids, associationType) {
26852         
26853         var associations     = record.associations.items,
26854             associationCount = associations.length,
26855             associationData  = {},
26856             associatedStore, associatedName, associatedRecords, associatedRecord,
26857             associatedRecordCount, association, id, i, j, type, allow;
26858
26859         for (i = 0; i < associationCount; i++) {
26860             association = associations[i];
26861             type = association.type;
26862             allow = true;
26863             if (associationType) {
26864                 allow = type == associationType;
26865             }
26866             if (allow && type == 'hasMany') {
26867
26868                 
26869                 associatedStore = record[association.storeName];
26870
26871                 
26872                 associationData[association.name] = [];
26873
26874                 
26875                 if (associatedStore && associatedStore.data.length > 0) {
26876                     associatedRecords = associatedStore.data.items;
26877                     associatedRecordCount = associatedRecords.length;
26878
26879                     
26880                     for (j = 0; j < associatedRecordCount; j++) {
26881                         associatedRecord = associatedRecords[j];
26882                         
26883                         id = associatedRecord.id;
26884
26885                         
26886                         
26887                         if (Ext.Array.indexOf(ids, id) == -1) {
26888                             ids.push(id);
26889
26890                             associationData[association.name][j] = associatedRecord.data;
26891                             Ext.apply(associationData[association.name][j], this.prepareAssociatedData(associatedRecord, ids, type));
26892                         }
26893                     }
26894                 }
26895             } else if (allow && type == 'belongsTo') {
26896                 associatedRecord = record[association.instanceName];
26897                 if (associatedRecord !== undefined) {
26898                     id = associatedRecord.id;
26899                     if (Ext.Array.indexOf(ids, id) == -1) {
26900                         ids.push(id);
26901                         associationData[association.name] = associatedRecord.data;
26902                         Ext.apply(associationData[association.name], this.prepareAssociatedData(associatedRecord, ids, type));
26903                     }
26904                 }
26905             }
26906         }
26907
26908         return associationData;
26909     }
26910 });
26911
26912
26913 Ext.define('Ext.data.StoreManager', {
26914     extend: 'Ext.util.MixedCollection',
26915     alternateClassName: ['Ext.StoreMgr', 'Ext.data.StoreMgr', 'Ext.StoreManager'],
26916     singleton: true,
26917     uses: ['Ext.data.ArrayStore'],
26918     
26919     
26920
26921     
26922     register : function() {
26923         for (var i = 0, s; (s = arguments[i]); i++) {
26924             this.add(s);
26925         }
26926     },
26927
26928     
26929     unregister : function() {
26930         for (var i = 0, s; (s = arguments[i]); i++) {
26931             this.remove(this.lookup(s));
26932         }
26933     },
26934
26935     
26936     lookup : function(store) {
26937         
26938         if (Ext.isArray(store)) {
26939             var fields = ['field1'], 
26940                 expand = !Ext.isArray(store[0]),
26941                 data = store,
26942                 i,
26943                 len;
26944                 
26945             if(expand){
26946                 data = [];
26947                 for (i = 0, len = store.length; i < len; ++i) {
26948                     data.push([store[i]]);
26949                 }
26950             } else {
26951                 for(i = 2, len = store[0].length; i <= len; ++i){
26952                     fields.push('field' + i);
26953                 }
26954             }
26955             return Ext.create('Ext.data.ArrayStore', {
26956                 data  : data,
26957                 fields: fields,
26958                 autoDestroy: true,
26959                 autoCreated: true,
26960                 expanded: expand
26961             });
26962         }
26963         
26964         if (Ext.isString(store)) {
26965             
26966             return this.get(store);
26967         } else {
26968             
26969             return Ext.data.AbstractStore.create(store);
26970         }
26971     },
26972
26973     
26974     getKey : function(o) {
26975          return o.storeId;
26976     }
26977 }, function() {    
26978     
26979     Ext.regStore = function(name, config) {
26980         var store;
26981
26982         if (Ext.isObject(name)) {
26983             config = name;
26984         } else {
26985             config.storeId = name;
26986         }
26987
26988         if (config instanceof Ext.data.Store) {
26989             store = config;
26990         } else {
26991             store = Ext.create('Ext.data.Store', config);
26992         }
26993
26994         return Ext.data.StoreManager.register(store);
26995     };
26996
26997     
26998     Ext.getStore = function(name) {
26999         return Ext.data.StoreManager.lookup(name);
27000     };
27001 });
27002
27003
27004 Ext.define('Ext.Component', {
27005
27006     
27007
27008     alias: ['widget.component', 'widget.box'],
27009
27010     extend: 'Ext.AbstractComponent',
27011
27012     requires: [
27013         'Ext.util.DelayedTask'
27014     ],
27015
27016     uses: [
27017         'Ext.Layer',
27018         'Ext.resizer.Resizer',
27019         'Ext.util.ComponentDragger'
27020     ],
27021
27022     mixins: {
27023         floating: 'Ext.util.Floating'
27024     },
27025
27026     statics: {
27027         
27028         DIRECTION_TOP: 'top',
27029         DIRECTION_RIGHT: 'right',
27030         DIRECTION_BOTTOM: 'bottom',
27031         DIRECTION_LEFT: 'left',
27032
27033         VERTICAL_DIRECTION_Re: /^(?:top|bottom)$/,
27034
27035         
27036         
27037         INVALID_ID_CHARS_Re: /[\.,\s]/g
27038     },
27039
27040     
27041
27042     
27043
27044     
27045     resizeHandles: 'all',
27046
27047     
27048
27049     
27050     floating: false,
27051
27052     
27053     toFrontOnShow: true,
27054
27055     
27056
27057     
27058
27059     
27060
27061     
27062
27063     hideMode: 'display',
27064     
27065     hideParent: false,
27066
27067     ariaRole: 'presentation',
27068
27069     bubbleEvents: [],
27070
27071     actionMode: 'el',
27072     monPropRe: /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
27073
27074     
27075     
27076     
27077     
27078     
27079     
27080
27081     
27082     constructor: function(config) {
27083         var me = this;
27084
27085         config = config || {};
27086         if (config.initialConfig) {
27087
27088             
27089             if (config.isAction) {
27090                 me.baseAction = config;
27091             }
27092             config = config.initialConfig;
27093             
27094         }
27095         else if (config.tagName || config.dom || Ext.isString(config)) {
27096             
27097             config = {
27098                 applyTo: config,
27099                 id: config.id || config
27100             };
27101         }
27102
27103         me.callParent([config]);
27104
27105         
27106         
27107         if (me.baseAction){
27108             me.baseAction.addComponent(me);
27109         }
27110     },
27111
27112     
27113     initComponent: function() {
27114         var me = this;
27115
27116         me.callParent();
27117
27118         if (me.listeners) {
27119             me.on(me.listeners);
27120             delete me.listeners;
27121         }
27122         me.enableBubble(me.bubbleEvents);
27123         me.mons = [];
27124     },
27125
27126     
27127     afterRender: function() {
27128         var me = this,
27129             resizable = me.resizable;
27130
27131         if (me.floating) {
27132             me.makeFloating(me.floating);
27133         } else {
27134             me.el.setVisibilityMode(Ext.Element[me.hideMode.toUpperCase()]);
27135         }
27136
27137         if (Ext.isDefined(me.autoScroll)) {
27138             me.setAutoScroll(me.autoScroll);
27139         }
27140         me.callParent();
27141
27142         if (!(me.x && me.y) && (me.pageX || me.pageY)) {
27143             me.setPagePosition(me.pageX, me.pageY);
27144         }
27145
27146         if (resizable) {
27147             me.initResizable(resizable);
27148         }
27149
27150         if (me.draggable) {
27151             me.initDraggable();
27152         }
27153
27154         me.initAria();
27155     },
27156
27157     initAria: function() {
27158         var actionEl = this.getActionEl(),
27159             role = this.ariaRole;
27160         if (role) {
27161             actionEl.dom.setAttribute('role', role);
27162         }
27163     },
27164
27165     
27166     setAutoScroll : function(scroll){
27167         var me = this,
27168             targetEl;
27169         scroll = !!scroll;
27170         if (me.rendered) {
27171             targetEl = me.getTargetEl();
27172             targetEl.setStyle('overflow', scroll ? 'auto' : '');
27173             if (scroll && (Ext.isIE6 || Ext.isIE7)) {
27174                 
27175                 
27176                 targetEl.position();
27177             }
27178         }
27179         me.autoScroll = scroll;
27180         return me;
27181     },
27182
27183     
27184     makeFloating : function(cfg){
27185         this.mixins.floating.constructor.call(this, cfg);
27186     },
27187
27188     initResizable: function(resizable) {
27189         var me = this;
27190
27191         resizable = Ext.apply({
27192             target: me,
27193             dynamic: false,
27194             constrainTo: me.constrainTo || (me.floatParent ? me.floatParent.getTargetEl() : me.el.getScopeParent()),
27195             handles: me.resizeHandles
27196         }, resizable);
27197         resizable.target = me;
27198         me.resizer = Ext.create('Ext.resizer.Resizer', resizable);
27199     },
27200
27201     getDragEl: function() {
27202         return this.el;
27203     },
27204
27205     initDraggable: function() {
27206         var me = this,
27207             ddConfig = Ext.applyIf({
27208                 el: me.getDragEl(),
27209                 constrainTo: me.constrain ? (me.constrainTo || (me.floatParent ? me.floatParent.getTargetEl() : me.el.getScopeParent())) : undefined
27210             }, me.draggable);
27211
27212         
27213         if (me.constrain || me.constrainDelegate) {
27214             ddConfig.constrain = me.constrain;
27215             ddConfig.constrainDelegate = me.constrainDelegate;
27216         }
27217
27218         me.dd = Ext.create('Ext.util.ComponentDragger', me, ddConfig);
27219     },
27220
27221     
27222     setPosition: function(x, y, animate) {
27223         var me = this,
27224             el = me.el,
27225             to = {},
27226             adj, adjX, adjY, xIsNumber, yIsNumber;
27227
27228         if (Ext.isArray(x)) {
27229             animate = y;
27230             y = x[1];
27231             x = x[0];
27232         }
27233         me.x = x;
27234         me.y = y;
27235
27236         if (!me.rendered) {
27237             return me;
27238         }
27239
27240         adj = me.adjustPosition(x, y);
27241         adjX = adj.x;
27242         adjY = adj.y;
27243         xIsNumber = Ext.isNumber(adjX);
27244         yIsNumber = Ext.isNumber(adjY);
27245
27246         if (xIsNumber || yIsNumber) {
27247             if (animate) {
27248                 if (xIsNumber) {
27249                     to.left = adjX;
27250                 }
27251                 if (yIsNumber) {
27252                     to.top = adjY;
27253                 }
27254
27255                 me.stopAnimation();
27256                 me.animate(Ext.apply({
27257                     duration: 1000,
27258                     listeners: {
27259                         afteranimate: Ext.Function.bind(me.afterSetPosition, me, [adjX, adjY])
27260                     },
27261                     to: to
27262                 }, animate));
27263             }
27264             else {
27265                 if (!xIsNumber) {
27266                     el.setTop(adjY);
27267                 }
27268                 else if (!yIsNumber) {
27269                     el.setLeft(adjX);
27270                 }
27271                 else {
27272                     el.setLeftTop(adjX, adjY);
27273                 }
27274                 me.afterSetPosition(adjX, adjY);
27275             }
27276         }
27277         return me;
27278     },
27279
27280     
27281     afterSetPosition: function(ax, ay) {
27282         this.onPosition(ax, ay);
27283         this.fireEvent('move', this, ax, ay);
27284     },
27285
27286     
27287     showAt: function(x, y, animate) {
27288         var me = this;
27289
27290         if (me.floating) {
27291             me.setPosition(x, y, animate);
27292         } else {
27293             me.setPagePosition(x, y, animate);
27294         }
27295         me.show();
27296     },
27297
27298     
27299     setPagePosition: function(x, y, animate) {
27300         var me = this,
27301             p;
27302
27303         if (Ext.isArray(x)) {
27304             y = x[1];
27305             x = x[0];
27306         }
27307         me.pageX = x;
27308         me.pageY = y;
27309         if (me.floating && me.floatParent) {
27310             
27311             p = me.floatParent.getTargetEl().getViewRegion();
27312             if (Ext.isNumber(x) && Ext.isNumber(p.left)) {
27313                 x -= p.left;
27314             }
27315             if (Ext.isNumber(y) && Ext.isNumber(p.top)) {
27316                 y -= p.top;
27317             }
27318             me.setPosition(x, y, animate);
27319         }
27320         else {
27321             p = me.el.translatePoints(x, y);
27322             me.setPosition(p.left, p.top, animate);
27323         }
27324         return me;
27325     },
27326
27327     
27328     getBox : function(local){
27329         var pos = this.getPosition(local),
27330             size = this.getSize();
27331
27332         size.x = pos[0];
27333         size.y = pos[1];
27334         return size;
27335     },
27336
27337     
27338     updateBox : function(box){
27339         this.setSize(box.width, box.height);
27340         this.setPagePosition(box.x, box.y);
27341         return this;
27342     },
27343
27344     
27345     getOuterSize: function() {
27346         var el = this.el;
27347         return {
27348             width: el.getWidth() + el.getMargin('lr'),
27349             height: el.getHeight() + el.getMargin('tb')
27350         };
27351     },
27352
27353     
27354     adjustPosition: function(x, y) {
27355
27356         
27357         if (this.floating && this.floatParent) {
27358             var o = this.floatParent.getTargetEl().getViewRegion();
27359             x += o.left;
27360             y += o.top;
27361         }
27362
27363         return {
27364             x: x,
27365             y: y
27366         };
27367     },
27368
27369     
27370     getPosition: function(local) {
27371         var me = this,
27372             el = me.el,
27373             xy,
27374             o;
27375
27376         
27377         if ((local === true) || (me.floating && !me.floatParent)) {
27378             return [el.getLeft(true), el.getTop(true)];
27379         }
27380         xy = me.xy || el.getXY();
27381
27382         
27383         if (me.floating) {
27384             o = me.floatParent.getTargetEl().getViewRegion();
27385             xy[0] -= o.left;
27386             xy[1] -= o.top;
27387         }
27388         return xy;
27389     },
27390
27391     getId: function() {
27392         var me = this,
27393             xtype;
27394
27395         if (!me.id) {
27396             xtype = me.getXType();
27397             xtype = xtype ? xtype.replace(Ext.Component.INVALID_ID_CHARS_Re, '-') : 'ext-comp';
27398             me.id = xtype + '-' + me.getAutoId();
27399         }
27400         return me.id;
27401     },
27402
27403     onEnable: function() {
27404         var actionEl = this.getActionEl();
27405         actionEl.dom.removeAttribute('aria-disabled');
27406         actionEl.dom.disabled = false;
27407         this.callParent();
27408     },
27409
27410     onDisable: function() {
27411         var actionEl = this.getActionEl();
27412         actionEl.dom.setAttribute('aria-disabled', true);
27413         actionEl.dom.disabled = true;
27414         this.callParent();
27415     },
27416
27417     
27418     show: function(animateTarget, cb, scope) {
27419         var me = this;
27420
27421         if (me.rendered && me.isVisible()) {
27422             if (me.toFrontOnShow && me.floating) {
27423                 me.toFront();
27424             }
27425         } else if (me.fireEvent('beforeshow', me) !== false) {
27426             me.hidden = false;
27427
27428             
27429             if (!me.rendered && (me.autoRender || me.floating)) {
27430                 me.doAutoRender();
27431             }
27432             if (me.rendered) {
27433                 me.beforeShow();
27434                 me.onShow.apply(me, arguments);
27435
27436                 
27437                 
27438                 if (me.ownerCt && !me.floating && !(me.ownerCt.suspendLayout || me.ownerCt.layout.layoutBusy)) {
27439                     me.ownerCt.doLayout();
27440                 }
27441                 me.afterShow.apply(me, arguments);
27442             }
27443         }
27444         return me;
27445     },
27446
27447     beforeShow: Ext.emptyFn,
27448
27449     
27450     onShow: function() {
27451         var me = this;
27452
27453         me.el.show();
27454         me.callParent(arguments);
27455         if (me.floating && me.constrain) {
27456             me.doConstrain();
27457         }
27458     },
27459
27460     afterShow: function(animateTarget, cb, scope) {
27461         var me = this,
27462             fromBox,
27463             toBox,
27464             ghostPanel;
27465
27466         
27467         animateTarget = animateTarget || me.animateTarget;
27468
27469         
27470         if (!me.ghost) {
27471             animateTarget = null;
27472         }
27473         
27474         if (animateTarget) {
27475             animateTarget = animateTarget.el ? animateTarget.el : Ext.get(animateTarget);
27476             toBox = me.el.getBox();
27477             fromBox = animateTarget.getBox();
27478             me.el.addCls(Ext.baseCSSPrefix + 'hide-offsets');
27479             ghostPanel = me.ghost();
27480             ghostPanel.el.stopAnimation();
27481
27482             
27483             ghostPanel.el.setX(-10000);
27484
27485             ghostPanel.el.animate({
27486                 from: fromBox,
27487                 to: toBox,
27488                 listeners: {
27489                     afteranimate: function() {
27490                         delete ghostPanel.componentLayout.lastComponentSize;
27491                         me.unghost();
27492                         me.el.removeCls(Ext.baseCSSPrefix + 'hide-offsets');
27493                         me.onShowComplete(cb, scope);
27494                     }
27495                 }
27496             });
27497         }
27498         else {
27499             me.onShowComplete(cb, scope);
27500         }
27501     },
27502
27503     onShowComplete: function(cb, scope) {
27504         var me = this;
27505         if (me.floating) {
27506             me.toFront();
27507         }
27508         Ext.callback(cb, scope || me);
27509         me.fireEvent('show', me);
27510     },
27511
27512     
27513     hide: function() {
27514         var me = this;
27515
27516         
27517         
27518         me.showOnParentShow = false;
27519
27520         if (!(me.rendered && !me.isVisible()) && me.fireEvent('beforehide', me) !== false) {
27521             me.hidden = true;
27522             if (me.rendered) {
27523                 me.onHide.apply(me, arguments);
27524
27525                 
27526                 
27527                 if (me.ownerCt && !me.floating && !(me.ownerCt.suspendLayout || me.ownerCt.layout.layoutBusy)) {
27528                     me.ownerCt.doLayout();
27529                 }
27530             }
27531         }
27532         return me;
27533     },
27534
27535     
27536     onHide: function(animateTarget, cb, scope) {
27537         var me = this,
27538             ghostPanel,
27539             toBox;
27540
27541         
27542         animateTarget = animateTarget || me.animateTarget;
27543
27544         
27545         if (!me.ghost) {
27546             animateTarget = null;
27547         }
27548         
27549         if (animateTarget) {
27550             animateTarget = animateTarget.el ? animateTarget.el : Ext.get(animateTarget);
27551             ghostPanel = me.ghost();
27552             ghostPanel.el.stopAnimation();
27553             toBox = animateTarget.getBox();
27554             toBox.width += 'px';
27555             toBox.height += 'px';
27556             ghostPanel.el.animate({
27557                 to: toBox,
27558                 listeners: {
27559                     afteranimate: function() {
27560                         delete ghostPanel.componentLayout.lastComponentSize;
27561                         ghostPanel.el.hide();
27562                         me.afterHide(cb, scope);
27563                     }
27564                 }
27565             });
27566         }
27567         me.el.hide();
27568         if (!animateTarget) {
27569             me.afterHide(cb, scope);
27570         }
27571     },
27572
27573     afterHide: function(cb, scope) {
27574         Ext.callback(cb, scope || this);
27575         this.fireEvent('hide', this);
27576     },
27577
27578     
27579     onDestroy: function() {
27580         var me = this;
27581
27582         
27583         if (me.rendered) {
27584             Ext.destroy(
27585                 me.proxy,
27586                 me.proxyWrap,
27587                 me.resizer
27588             );
27589             
27590             if (me.actionMode == 'container' || me.removeMode == 'container') {
27591                 me.container.remove();
27592             }
27593         }
27594         delete me.focusTask;
27595         me.callParent();
27596     },
27597
27598     deleteMembers: function() {
27599         var args = arguments,
27600             len = args.length,
27601             i = 0;
27602         for (; i < len; ++i) {
27603             delete this[args[i]];
27604         }
27605     },
27606
27607     
27608     focus: function(selectText, delay) {
27609         var me = this,
27610                 focusEl;
27611
27612         if (delay) {
27613             if (!me.focusTask) {
27614                 me.focusTask = Ext.create('Ext.util.DelayedTask', me.focus);
27615             }
27616             me.focusTask.delay(Ext.isNumber(delay) ? delay : 10, null, me, [selectText, false]);
27617             return me;
27618         }
27619
27620         if (me.rendered && !me.isDestroyed) {
27621             
27622             focusEl = me.getFocusEl();
27623             focusEl.focus();
27624             if (focusEl.dom && selectText === true) {
27625                 focusEl.dom.select();
27626             }
27627
27628             
27629             
27630             if (me.floating) {
27631                 me.toFront(true);
27632             }
27633         }
27634         return me;
27635     },
27636
27637     
27638     getFocusEl: function() {
27639         return this.el;
27640     },
27641
27642     
27643     blur: function() {
27644         if (this.rendered) {
27645             this.getFocusEl().blur();
27646         }
27647         return this;
27648     },
27649
27650     getEl: function() {
27651         return this.el;
27652     },
27653
27654     
27655     getResizeEl: function() {
27656         return this.el;
27657     },
27658
27659     
27660     getPositionEl: function() {
27661         return this.el;
27662     },
27663
27664     
27665     getActionEl: function() {
27666         return this.el;
27667     },
27668
27669     
27670     getVisibilityEl: function() {
27671         return this.el;
27672     },
27673
27674     
27675     onResize: Ext.emptyFn,
27676
27677     
27678     getBubbleTarget: function() {
27679         return this.ownerCt;
27680     },
27681
27682     
27683     getContentTarget: function() {
27684         return this.el;
27685     },
27686
27687     
27688     cloneConfig: function(overrides) {
27689         overrides = overrides || {};
27690         var id = overrides.id || Ext.id(),
27691             cfg = Ext.applyIf(overrides, this.initialConfig),
27692             self;
27693
27694         cfg.id = id;
27695
27696         self = Ext.getClass(this);
27697
27698         
27699         return new self(cfg);
27700     },
27701
27702     
27703     getXType: function() {
27704         return this.self.xtype;
27705     },
27706
27707     
27708     findParentBy: function(fn) {
27709         var p;
27710
27711         
27712         for (p = this.ownerCt; p && !fn(p, this); p = p.ownerCt);
27713         return p || null;
27714     },
27715
27716     
27717     findParentByType: function(xtype) {
27718         return Ext.isFunction(xtype) ?
27719             this.findParentBy(function(p) {
27720                 return p.constructor === xtype;
27721             })
27722         :
27723             this.up(xtype);
27724     },
27725
27726     
27727     bubble: function(fn, scope, args) {
27728         var p = this;
27729         while (p) {
27730             if (fn.apply(scope || p, args || [p]) === false) {
27731                 break;
27732             }
27733             p = p.ownerCt;
27734         }
27735         return this;
27736     },
27737
27738     getProxy: function() {
27739         var me = this,
27740             target;
27741
27742         if (!me.proxy) {
27743             target = Ext.getBody();
27744             if (Ext.scopeResetCSS) {
27745                 me.proxyWrap = target = Ext.getBody().createChild({
27746                     cls: Ext.baseCSSPrefix + 'reset'
27747                 });
27748             }
27749             me.proxy = me.el.createProxy(Ext.baseCSSPrefix + 'proxy-el', target, true);
27750         }
27751         return me.proxy;
27752     }
27753
27754 });
27755
27756
27757 Ext.define('Ext.layout.container.AbstractContainer', {
27758
27759     
27760
27761     extend: 'Ext.layout.Layout',
27762
27763     
27764
27765     type: 'container',
27766
27767     
27768     bindToOwnerCtComponent: false,
27769
27770     
27771     bindToOwnerCtContainer: false,
27772
27773     
27774
27775     
27776     setItemSize: function(item, width, height) {
27777         if (Ext.isObject(width)) {
27778             height = width.height;
27779             width = width.width;
27780         }
27781         item.setCalculatedSize(width, height, this.owner);
27782     },
27783
27784     
27785     getLayoutItems: function() {
27786         return this.owner && this.owner.items && this.owner.items.items || [];
27787     },
27788
27789     
27790     beforeLayout: function() {
27791         return !this.owner.collapsed && this.callParent(arguments);
27792     },
27793
27794     afterLayout: function() {
27795         this.owner.afterLayout(this);
27796     },
27797     
27798      getTarget: function() {
27799          return this.owner.getTargetEl();
27800      },
27801     
27802      getRenderTarget: function() {
27803          return this.owner.getTargetEl();
27804      }
27805 });
27806
27807
27808 Ext.define('Ext.layout.container.Container', {
27809
27810     
27811
27812     extend: 'Ext.layout.container.AbstractContainer',
27813     alternateClassName: 'Ext.layout.ContainerLayout',
27814
27815     
27816
27817     layoutItem: function(item, box) {
27818         if (box) {
27819             item.doComponentLayout(box.width, box.height);
27820         } else {
27821             item.doComponentLayout();
27822         }
27823     },
27824
27825     getLayoutTargetSize : function() {
27826         var target = this.getTarget(),
27827             ret;
27828
27829         if (target) {
27830             ret = target.getViewSize();
27831
27832             
27833             
27834             
27835             if (Ext.isIE && ret.width == 0){
27836                 ret = target.getStyleSize();
27837             }
27838
27839             ret.width -= target.getPadding('lr');
27840             ret.height -= target.getPadding('tb');
27841         }
27842         return ret;
27843     },
27844
27845     beforeLayout: function() {
27846         if (this.owner.beforeLayout(arguments) !== false) {
27847             return this.callParent(arguments);
27848         }
27849         else {
27850             return false;
27851         }
27852     },
27853
27854     
27855     getRenderedItems: function() {
27856         var me = this,
27857             target = me.getTarget(),
27858             items = me.getLayoutItems(),
27859             ln = items.length,
27860             renderedItems = [],
27861             i, item;
27862
27863         for (i = 0; i < ln; i++) {
27864             item = items[i];
27865             if (item.rendered && me.isValidParent(item, target, i)) {
27866                 renderedItems.push(item);
27867             }
27868         }
27869
27870         return renderedItems;
27871     },
27872
27873     
27874     getVisibleItems: function() {
27875         var target   = this.getTarget(),
27876             items = this.getLayoutItems(),
27877             ln = items.length,
27878             visibleItems = [],
27879             i, item;
27880
27881         for (i = 0; i < ln; i++) {
27882             item = items[i];
27883             if (item.rendered && this.isValidParent(item, target, i) && item.hidden !== true) {
27884                 visibleItems.push(item);
27885             }
27886         }
27887
27888         return visibleItems;
27889     }
27890 });
27891
27892 Ext.define('Ext.layout.container.Auto', {
27893
27894     
27895
27896     alias: ['layout.auto', 'layout.autocontainer'],
27897
27898     extend: 'Ext.layout.container.Container',
27899
27900     
27901
27902     type: 'autocontainer',
27903
27904     bindToOwnerCtComponent: true,
27905
27906     
27907     onLayout : function(owner, target) {
27908         var me = this,
27909             items = me.getLayoutItems(),
27910             ln = items.length,
27911             i;
27912
27913         
27914         if (ln) {
27915             
27916             
27917             
27918             if (!me.clearEl) {
27919                 me.clearEl = me.getRenderTarget().createChild({
27920                     cls: Ext.baseCSSPrefix + 'clear',
27921                     role: 'presentation'
27922                 });
27923             }
27924
27925             
27926             for (i = 0; i < ln; i++) {
27927                 me.setItemSize(items[i]);
27928             }
27929         }
27930     },
27931
27932     configureItem: function(item) {
27933         this.callParent(arguments);
27934
27935         
27936         item.layoutManagedHeight = 2;
27937         item.layoutManagedWidth = 2;
27938     }
27939 });
27940
27941 Ext.define('Ext.container.AbstractContainer', {
27942
27943     
27944
27945     extend: 'Ext.Component',
27946
27947     requires: [
27948         'Ext.util.MixedCollection',
27949         'Ext.layout.container.Auto',
27950         'Ext.ZIndexManager'
27951     ],
27952
27953     
27954     
27955
27956     
27957     
27958     
27959
27960     
27961     suspendLayout : false,
27962
27963     
27964     autoDestroy : true,
27965
27966      
27967     defaultType: 'panel',
27968
27969     isContainer : true,
27970
27971     
27972     layoutCounter : 0,
27973
27974     baseCls: Ext.baseCSSPrefix + 'container',
27975
27976     
27977     bubbleEvents: ['add', 'remove'],
27978
27979     
27980     initComponent : function(){
27981         var me = this;
27982         me.addEvents(
27983             
27984             'afterlayout',
27985             
27986             'beforeadd',
27987             
27988             'beforeremove',
27989             
27990             'add',
27991             
27992             'remove'
27993         );
27994
27995         
27996         me.layoutOnShow = Ext.create('Ext.util.MixedCollection');
27997         me.callParent();
27998         me.initItems();
27999     },
28000
28001     
28002     initItems : function() {
28003         var me = this,
28004             items = me.items;
28005
28006         
28007         me.items = Ext.create('Ext.util.MixedCollection', false, me.getComponentId);
28008
28009         if (items) {
28010             if (!Ext.isArray(items)) {
28011                 items = [items];
28012             }
28013
28014             me.add(items);
28015         }
28016     },
28017
28018     
28019     afterRender : function() {
28020         this.getLayout();
28021         this.callParent();
28022     },
28023
28024     renderChildren: function () {
28025         var me = this,
28026             layout = me.getLayout();
28027
28028         me.callParent();
28029         
28030
28031         if (layout) {
28032             me.suspendLayout = true;
28033             layout.renderChildren();
28034             delete me.suspendLayout;
28035         }
28036     },
28037
28038     
28039     setLayout : function(layout) {
28040         var currentLayout = this.layout;
28041
28042         if (currentLayout && currentLayout.isLayout && currentLayout != layout) {
28043             currentLayout.setOwner(null);
28044         }
28045
28046         this.layout = layout;
28047         layout.setOwner(this);
28048     },
28049
28050     
28051     getLayout : function() {
28052         var me = this;
28053         if (!me.layout || !me.layout.isLayout) {
28054             me.setLayout(Ext.layout.Layout.create(me.layout, 'autocontainer'));
28055         }
28056
28057         return me.layout;
28058     },
28059
28060     
28061     doLayout : function() {
28062         var me = this,
28063             layout = me.getLayout();
28064
28065         if (me.rendered && layout && !me.suspendLayout) {
28066             
28067             if (!me.isFixedWidth() || !me.isFixedHeight()) {
28068                 
28069                 if (me.componentLayout.layoutBusy !== true) {
28070                     me.doComponentLayout();
28071                     if (me.componentLayout.layoutCancelled === true) {
28072                         layout.layout();
28073                     }
28074                 }
28075             }
28076             
28077             else {
28078                 
28079                 if (layout.layoutBusy !== true) {
28080                     layout.layout();
28081                 }
28082             }
28083         }
28084
28085         return me;
28086     },
28087
28088     
28089     afterLayout : function(layout) {
28090         ++this.layoutCounter;
28091         this.fireEvent('afterlayout', this, layout);
28092     },
28093
28094     
28095     prepareItems : function(items, applyDefaults) {
28096         if (!Ext.isArray(items)) {
28097             items = [items];
28098         }
28099
28100         
28101         var i = 0,
28102             len = items.length,
28103             item;
28104
28105         for (; i < len; i++) {
28106             item = items[i];
28107             if (applyDefaults) {
28108                 item = this.applyDefaults(item);
28109             }
28110             items[i] = this.lookupComponent(item);
28111         }
28112         return items;
28113     },
28114
28115     
28116     applyDefaults : function(config) {
28117         var defaults = this.defaults;
28118
28119         if (defaults) {
28120             if (Ext.isFunction(defaults)) {
28121                 defaults = defaults.call(this, config);
28122             }
28123
28124             if (Ext.isString(config)) {
28125                 config = Ext.ComponentManager.get(config);
28126             }
28127             Ext.applyIf(config, defaults);
28128         }
28129
28130         return config;
28131     },
28132
28133     
28134     lookupComponent : function(comp) {
28135         return Ext.isString(comp) ? Ext.ComponentManager.get(comp) : this.createComponent(comp);
28136     },
28137
28138     
28139     createComponent : function(config, defaultType) {
28140         
28141         
28142         
28143         
28144         
28145         
28146
28147         return Ext.ComponentManager.create(config, defaultType || this.defaultType);
28148     },
28149
28150     
28151     getComponentId : function(comp) {
28152         return comp.getItemId();
28153     },
28154
28155     
28156     add : function() {
28157         var me = this,
28158             args = Array.prototype.slice.call(arguments),
28159             hasMultipleArgs,
28160             items,
28161             results = [],
28162             i,
28163             ln,
28164             item,
28165             index = -1,
28166             cmp;
28167
28168         if (typeof args[0] == 'number') {
28169             index = args.shift();
28170         }
28171
28172         hasMultipleArgs = args.length > 1;
28173         if (hasMultipleArgs || Ext.isArray(args[0])) {
28174
28175             items = hasMultipleArgs ? args : args[0];
28176             
28177             me.suspendLayout = true;
28178             for (i = 0, ln = items.length; i < ln; i++) {
28179                 item = items[i];
28180
28181
28182                 if (index != -1) {
28183                     item = me.add(index + i, item);
28184                 } else {
28185                     item = me.add(item);
28186                 }
28187                 results.push(item);
28188             }
28189             
28190             me.suspendLayout = false;
28191             me.doLayout();
28192             return results;
28193         }
28194
28195         cmp = me.prepareItems(args[0], true)[0];
28196
28197         
28198         
28199         
28200         if (cmp.floating) {
28201             cmp.onAdded(me, index);
28202         } else {
28203             index = (index !== -1) ? index : me.items.length;
28204             if (me.fireEvent('beforeadd', me, cmp, index) !== false && me.onBeforeAdd(cmp) !== false) {
28205                 me.items.insert(index, cmp);
28206                 cmp.onAdded(me, index);
28207                 me.onAdd(cmp, index);
28208                 me.fireEvent('add', me, cmp, index);
28209             }
28210             me.doLayout();
28211         }
28212         return cmp;
28213     },
28214
28215     onAdd : Ext.emptyFn,
28216     onRemove : Ext.emptyFn,
28217
28218     
28219     insert : function(index, comp) {
28220         return this.add(index, comp);
28221     },
28222
28223     
28224     move : function(fromIdx, toIdx) {
28225         var items = this.items,
28226             item;
28227         item = items.removeAt(fromIdx);
28228         if (item === false) {
28229             return false;
28230         }
28231         items.insert(toIdx, item);
28232         this.doLayout();
28233         return item;
28234     },
28235
28236     
28237     onBeforeAdd : function(item) {
28238         var me = this;
28239
28240         if (item.ownerCt) {
28241             item.ownerCt.remove(item, false);
28242         }
28243
28244         if (me.border === false || me.border === 0) {
28245             item.border = (item.border === true);
28246         }
28247     },
28248
28249     
28250     remove : function(comp, autoDestroy) {
28251         var me = this,
28252             c = me.getComponent(comp);
28253
28254         if (c && me.fireEvent('beforeremove', me, c) !== false) {
28255             me.doRemove(c, autoDestroy);
28256             me.fireEvent('remove', me, c);
28257         }
28258
28259         return c;
28260     },
28261
28262     
28263     doRemove : function(component, autoDestroy) {
28264         var me = this,
28265             layout = me.layout,
28266             hasLayout = layout && me.rendered;
28267
28268         me.items.remove(component);
28269         component.onRemoved();
28270
28271         if (hasLayout) {
28272             layout.onRemove(component);
28273         }
28274
28275         me.onRemove(component, autoDestroy);
28276
28277         if (autoDestroy === true || (autoDestroy !== false && me.autoDestroy)) {
28278             component.destroy();
28279         }
28280
28281         if (hasLayout && !autoDestroy) {
28282             layout.afterRemove(component);
28283         }
28284
28285         if (!me.destroying) {
28286             me.doLayout();
28287         }
28288     },
28289
28290     
28291     removeAll : function(autoDestroy) {
28292         var me = this,
28293             removeItems = me.items.items.slice(),
28294             items = [],
28295             i = 0,
28296             len = removeItems.length,
28297             item;
28298
28299         
28300         me.suspendLayout = true;
28301         for (; i < len; i++) {
28302             item = removeItems[i];
28303             me.remove(item, autoDestroy);
28304
28305             if (item.ownerCt !== me) {
28306                 items.push(item);
28307             }
28308         }
28309
28310         
28311         me.suspendLayout = false;
28312         if (len) {
28313             me.doLayout();
28314         }
28315         return items;
28316     },
28317
28318     
28319     
28320     
28321     
28322     
28323     
28324     
28325     
28326     getRefItems : function(deep) {
28327         var me = this,
28328             items = me.items.items,
28329             len = items.length,
28330             i = 0,
28331             item,
28332             result = [];
28333
28334         for (; i < len; i++) {
28335             item = items[i];
28336             result.push(item);
28337             if (deep && item.getRefItems) {
28338                 result.push.apply(result, item.getRefItems(true));
28339             }
28340         }
28341
28342         
28343         
28344         if (me.floatingItems && me.floatingItems.accessList) {
28345             result.push.apply(result, me.floatingItems.accessList);
28346         }
28347
28348         return result;
28349     },
28350
28351     
28352     cascade : function(fn, scope, origArgs){
28353         var me = this,
28354             cs = me.items ? me.items.items : [],
28355             len = cs.length,
28356             i = 0,
28357             c,
28358             args = origArgs ? origArgs.concat(me) : [me],
28359             componentIndex = args.length - 1;
28360
28361         if (fn.apply(scope || me, args) !== false) {
28362             for(; i < len; i++){
28363                 c = cs[i];
28364                 if (c.cascade) {
28365                     c.cascade(fn, scope, origArgs);
28366                 } else {
28367                     args[componentIndex] = c;
28368                     fn.apply(scope || cs, args);
28369                 }
28370             }
28371         }
28372         return this;
28373     },
28374
28375     
28376     getComponent : function(comp) {
28377         if (Ext.isObject(comp)) {
28378             comp = comp.getItemId();
28379         }
28380
28381         return this.items.get(comp);
28382     },
28383
28384     
28385     query : function(selector) {
28386         selector = selector || '*';
28387         return Ext.ComponentQuery.query(selector, this);
28388     },
28389
28390     
28391     child : function(selector) {
28392         selector = selector || '';
28393         return this.query('> ' + selector)[0] || null;
28394     },
28395
28396     
28397     down : function(selector) {
28398         return this.query(selector)[0] || null;
28399     },
28400
28401     
28402     show : function() {
28403         this.callParent(arguments);
28404         this.performDeferredLayouts();
28405         return this;
28406     },
28407
28408     
28409     
28410     performDeferredLayouts: function() {
28411         var layoutCollection = this.layoutOnShow,
28412             ln = layoutCollection.getCount(),
28413             i = 0,
28414             needsLayout,
28415             item;
28416
28417         for (; i < ln; i++) {
28418             item = layoutCollection.get(i);
28419             needsLayout = item.needsLayout;
28420
28421             if (Ext.isObject(needsLayout)) {
28422                 item.doComponentLayout(needsLayout.width, needsLayout.height, needsLayout.isSetSize, needsLayout.ownerCt);
28423             }
28424         }
28425         layoutCollection.clear();
28426     },
28427
28428     //@private
28429
28430     
28431     onEnable: function() {
28432         Ext.Array.each(this.query('[isFormField]'), function(item) {
28433             if (item.resetDisable) {
28434                 item.enable();
28435                 delete item.resetDisable;
28436             }
28437         });
28438         this.callParent();
28439     },
28440
28441     
28442     
28443     onDisable: function() {
28444         Ext.Array.each(this.query('[isFormField]'), function(item) {
28445             if (item.resetDisable !== false && !item.disabled) {
28446                 item.disable();
28447                 item.resetDisable = true;
28448             }
28449         });
28450         this.callParent();
28451     },
28452
28453     
28454     beforeLayout: function() {
28455         return true;
28456     },
28457
28458     
28459     beforeDestroy : function() {
28460         var me = this,
28461             items = me.items,
28462             c;
28463
28464         if (items) {
28465             while ((c = items.first())) {
28466                 me.doRemove(c, true);
28467             }
28468         }
28469
28470         Ext.destroy(
28471             me.layout
28472         );
28473         me.callParent();
28474     }
28475 });
28476
28477
28478 Ext.define('Ext.container.Container', {
28479     extend: 'Ext.container.AbstractContainer',
28480     alias: 'widget.container',
28481     alternateClassName: 'Ext.Container',
28482
28483     
28484     getChildByElement: function(el) {
28485         var item,
28486             itemEl,
28487             i = 0,
28488             it = this.items.items,
28489             ln = it.length;
28490
28491         el = Ext.getDom(el);
28492         for (; i < ln; i++) {
28493             item = it[i];
28494             itemEl = item.getEl();
28495             if ((itemEl.dom === el) || itemEl.contains(el)) {
28496                 return item;
28497             }
28498         }
28499         return null;
28500     }
28501 });
28502
28503
28504 Ext.define('Ext.toolbar.Fill', {
28505     extend: 'Ext.Component',
28506     alias: 'widget.tbfill',
28507     alternateClassName: 'Ext.Toolbar.Fill',
28508     isFill : true,
28509     flex: 1
28510 });
28511
28512 Ext.define('Ext.toolbar.Item', {
28513     extend: 'Ext.Component',
28514     alias: 'widget.tbitem',
28515     alternateClassName: 'Ext.Toolbar.Item',
28516     enable:Ext.emptyFn,
28517     disable:Ext.emptyFn,
28518     focus:Ext.emptyFn
28519     
28520 });
28521
28522 Ext.define('Ext.toolbar.Separator', {
28523     extend: 'Ext.toolbar.Item',
28524     alias: 'widget.tbseparator',
28525     alternateClassName: 'Ext.Toolbar.Separator',
28526     baseCls: Ext.baseCSSPrefix + 'toolbar-separator',
28527     focusable: false
28528 });
28529
28530 Ext.define('Ext.menu.Manager', {
28531     singleton: true,
28532     requires: [
28533         'Ext.util.MixedCollection',
28534         'Ext.util.KeyMap'
28535     ],
28536     alternateClassName: 'Ext.menu.MenuMgr',
28537
28538     uses: ['Ext.menu.Menu'],
28539
28540     menus: {},
28541     groups: {},
28542     attached: false,
28543     lastShow: new Date(),
28544
28545     init: function() {
28546         var me = this;
28547         
28548         me.active = Ext.create('Ext.util.MixedCollection');
28549         Ext.getDoc().addKeyListener(27, function() {
28550             if (me.active.length > 0) {
28551                 me.hideAll();
28552             }
28553         }, me);
28554     },
28555
28556     
28557     hideAll: function() {
28558         var active = this.active,
28559             c;
28560         if (active && active.length > 0) {
28561             c = active.clone();
28562             c.each(function(m) {
28563                 m.hide();
28564             });
28565             return true;
28566         }
28567         return false;
28568     },
28569
28570     onHide: function(m) {
28571         var me = this,
28572             active = me.active;
28573         active.remove(m);
28574         if (active.length < 1) {
28575             Ext.getDoc().un('mousedown', me.onMouseDown, me);
28576             me.attached = false;
28577         }
28578     },
28579
28580     onShow: function(m) {
28581         var me = this,
28582             active   = me.active,
28583             last     = active.last(),
28584             attached = me.attached,
28585             menuEl   = m.getEl(),
28586             zIndex;
28587
28588         me.lastShow = new Date();
28589         active.add(m);
28590         if (!attached) {
28591             Ext.getDoc().on('mousedown', me.onMouseDown, me);
28592             me.attached = true;
28593         }
28594         m.toFront();
28595     },
28596
28597     onBeforeHide: function(m) {
28598         if (m.activeChild) {
28599             m.activeChild.hide();
28600         }
28601         if (m.autoHideTimer) {
28602             clearTimeout(m.autoHideTimer);
28603             delete m.autoHideTimer;
28604         }
28605     },
28606
28607     onBeforeShow: function(m) {
28608         var active = this.active,
28609             parentMenu = m.parentMenu;
28610             
28611         active.remove(m);
28612         if (!parentMenu && !m.allowOtherMenus) {
28613             this.hideAll();
28614         }
28615         else if (parentMenu && parentMenu.activeChild && m != parentMenu.activeChild) {
28616             parentMenu.activeChild.hide();
28617         }
28618     },
28619
28620     
28621     onMouseDown: function(e) {
28622         var me = this,
28623             active = me.active,
28624             lastShow = me.lastShow,
28625             target = e.target;
28626
28627         if (Ext.Date.getElapsed(lastShow) > 50 && active.length > 0 && !e.getTarget('.' + Ext.baseCSSPrefix + 'menu')) {
28628             me.hideAll();
28629             
28630             
28631             if (Ext.isIE && Ext.fly(target).focusable()) {
28632                 target.focus();
28633             }
28634         }
28635     },
28636
28637     
28638     register: function(menu) {
28639         var me = this;
28640
28641         if (!me.active) {
28642             me.init();
28643         }
28644
28645         if (menu.floating) {
28646             me.menus[menu.id] = menu;
28647             menu.on({
28648                 beforehide: me.onBeforeHide,
28649                 hide: me.onHide,
28650                 beforeshow: me.onBeforeShow,
28651                 show: me.onShow,
28652                 scope: me
28653             });
28654         }
28655     },
28656
28657     
28658     get: function(menu) {
28659         var menus = this.menus;
28660         
28661         if (typeof menu == 'string') { 
28662             if (!menus) {  
28663                 return null;
28664             }
28665             return menus[menu];
28666         } else if (menu.isMenu) {  
28667             return menu;
28668         } else if (Ext.isArray(menu)) { 
28669             return Ext.create('Ext.menu.Menu', {items:menu});
28670         } else { 
28671             return Ext.ComponentManager.create(menu, 'menu');
28672         }
28673     },
28674
28675     
28676     unregister: function(menu) {
28677         var me = this,
28678             menus = me.menus,
28679             active = me.active;
28680
28681         delete menus[menu.id];
28682         active.remove(menu);
28683         menu.un({
28684             beforehide: me.onBeforeHide,
28685             hide: me.onHide,
28686             beforeshow: me.onBeforeShow,
28687             show: me.onShow,
28688             scope: me
28689         });
28690     },
28691
28692     
28693     registerCheckable: function(menuItem) {
28694         var groups  = this.groups,
28695             groupId = menuItem.group;
28696
28697         if (groupId) {
28698             if (!groups[groupId]) {
28699                 groups[groupId] = [];
28700             }
28701
28702             groups[groupId].push(menuItem);
28703         }
28704     },
28705
28706     
28707     unregisterCheckable: function(menuItem) {
28708         var groups  = this.groups,
28709             groupId = menuItem.group;
28710
28711         if (groupId) {
28712             Ext.Array.remove(groups[groupId], menuItem);
28713         }
28714     },
28715
28716     onCheckChange: function(menuItem, state) {
28717         var groups  = this.groups,
28718             groupId = menuItem.group,
28719             i       = 0,
28720             group, ln, curr;
28721
28722         if (groupId && state) {
28723             group = groups[groupId];
28724             ln = group.length;
28725             for (; i < ln; i++) {
28726                 curr = group[i];
28727                 if (curr != menuItem) {
28728                     curr.setChecked(false);
28729                 }
28730             }
28731         }
28732     }
28733 });
28734
28735 Ext.define('Ext.layout.component.Button', {
28736
28737     
28738
28739     alias: ['layout.button'],
28740
28741     extend: 'Ext.layout.component.Component',
28742
28743     
28744
28745     type: 'button',
28746
28747     cellClsRE: /-btn-(tl|br)\b/,
28748     htmlRE: /<.*>/,
28749
28750     beforeLayout: function() {
28751         return this.callParent(arguments) || this.lastText !== this.owner.text;
28752     },
28753
28754     
28755     onLayout: function(width, height) {
28756         var me = this,
28757             isNum = Ext.isNumber,
28758             owner = me.owner,
28759             ownerEl = owner.el,
28760             btnEl = owner.btnEl,
28761             btnInnerEl = owner.btnInnerEl,
28762             btnIconEl = owner.btnIconEl,
28763             sizeIconEl = (owner.icon || owner.iconCls) && (owner.iconAlign == "top" || owner.iconAlign == "bottom"),
28764             minWidth = owner.minWidth,
28765             maxWidth = owner.maxWidth,
28766             ownerWidth, btnFrameWidth, metrics;
28767
28768         me.getTargetInfo();
28769         me.callParent(arguments);
28770
28771         btnInnerEl.unclip();
28772         me.setTargetSize(width, height);
28773
28774         if (!isNum(width)) {
28775             
28776             
28777             
28778             if (owner.text && (Ext.isIE6 || Ext.isIE7) && Ext.isStrict && btnEl && btnEl.getWidth() > 20) {
28779                 btnFrameWidth = me.btnFrameWidth;
28780                 metrics = Ext.util.TextMetrics.measure(btnInnerEl, owner.text);
28781                 ownerEl.setWidth(metrics.width + btnFrameWidth + me.adjWidth);
28782                 btnEl.setWidth(metrics.width + btnFrameWidth);
28783                 btnInnerEl.setWidth(metrics.width + btnFrameWidth);
28784
28785                 if (sizeIconEl) {
28786                     btnIconEl.setWidth(metrics.width + btnFrameWidth);
28787                 }
28788             } else {
28789                 
28790                 ownerEl.setWidth(null);
28791                 btnEl.setWidth(null);
28792                 btnInnerEl.setWidth(null);
28793                 btnIconEl.setWidth(null);
28794             }
28795
28796             
28797             if (minWidth || maxWidth) {
28798                 ownerWidth = ownerEl.getWidth();
28799                 if (minWidth && (ownerWidth < minWidth)) {
28800                     me.setTargetSize(minWidth, height);
28801                 }
28802                 else if (maxWidth && (ownerWidth > maxWidth)) {
28803                     btnInnerEl.clip();
28804                     me.setTargetSize(maxWidth, height);
28805                 }
28806             }
28807         }
28808
28809         this.lastText = owner.text;
28810     },
28811
28812     setTargetSize: function(width, height) {
28813         var me = this,
28814             owner = me.owner,
28815             isNum = Ext.isNumber,
28816             btnInnerEl = owner.btnInnerEl,
28817             btnWidth = (isNum(width) ? width - me.adjWidth : width),
28818             btnHeight = (isNum(height) ? height - me.adjHeight : height),
28819             btnFrameHeight = me.btnFrameHeight,
28820             text = owner.getText(),
28821             textHeight;
28822
28823         me.callParent(arguments);
28824         me.setElementSize(owner.btnEl, btnWidth, btnHeight);
28825         me.setElementSize(btnInnerEl, btnWidth, btnHeight);
28826         if (btnHeight >= 0) {
28827             btnInnerEl.setStyle('line-height', btnHeight - btnFrameHeight + 'px');
28828         }
28829
28830         
28831         
28832         
28833         
28834         
28835         if (text && this.htmlRE.test(text)) {
28836             btnInnerEl.setStyle('line-height', 'normal');
28837             textHeight = Ext.util.TextMetrics.measure(btnInnerEl, text).height;
28838             btnInnerEl.setStyle('padding-top', me.btnFrameTop + Math.max(btnInnerEl.getHeight() - btnFrameHeight - textHeight, 0) / 2 + 'px');
28839             me.setElementSize(btnInnerEl, btnWidth, btnHeight);
28840         }
28841     },
28842
28843     getTargetInfo: function() {
28844         var me = this,
28845             owner = me.owner,
28846             ownerEl = owner.el,
28847             frameSize = me.frameSize,
28848             frameBody = owner.frameBody,
28849             btnWrap = owner.btnWrap,
28850             innerEl = owner.btnInnerEl;
28851
28852         if (!('adjWidth' in me)) {
28853             Ext.apply(me, {
28854                 
28855                 adjWidth: frameSize.left + frameSize.right + ownerEl.getBorderWidth('lr') + ownerEl.getPadding('lr') +
28856                           btnWrap.getPadding('lr') + (frameBody ? frameBody.getFrameWidth('lr') : 0),
28857                 adjHeight: frameSize.top + frameSize.bottom + ownerEl.getBorderWidth('tb') + ownerEl.getPadding('tb') +
28858                            btnWrap.getPadding('tb') + (frameBody ? frameBody.getFrameWidth('tb') : 0),
28859                 btnFrameWidth: innerEl.getFrameWidth('lr'),
28860                 btnFrameHeight: innerEl.getFrameWidth('tb'),
28861                 btnFrameTop: innerEl.getFrameWidth('t')
28862             });
28863         }
28864
28865         return me.callParent();
28866     }
28867 });
28868
28869 Ext.define('Ext.button.Button', {
28870
28871     
28872     alias: 'widget.button',
28873     extend: 'Ext.Component',
28874
28875     requires: [
28876         'Ext.menu.Manager',
28877         'Ext.util.ClickRepeater',
28878         'Ext.layout.component.Button',
28879         'Ext.util.TextMetrics',
28880         'Ext.util.KeyMap'
28881     ],
28882
28883     alternateClassName: 'Ext.Button',
28884     
28885
28886     isButton: true,
28887     componentLayout: 'button',
28888
28889     
28890     hidden: false,
28891
28892     
28893     disabled: false,
28894
28895     
28896     pressed: false,
28897
28898     
28899
28900     
28901
28902     
28903
28904     
28905
28906     
28907
28908     
28909
28910     
28911
28912     
28913
28914     
28915
28916     
28917
28918     
28919
28920     
28921
28922     
28923     enableToggle: false,
28924
28925     
28926
28927     
28928
28929     
28930     menuAlign: 'tl-bl?',
28931
28932     
28933     textAlign: 'center',
28934
28935     
28936
28937     
28938
28939     
28940     type: 'button',
28941
28942     
28943     clickEvent: 'click',
28944
28945     
28946     preventDefault: true,
28947
28948     
28949     handleMouseEvents: true,
28950
28951     
28952     tooltipType: 'qtip',
28953
28954     
28955     baseCls: Ext.baseCSSPrefix + 'btn',
28956
28957     
28958     pressedCls: 'pressed',
28959
28960     
28961     overCls: 'over',
28962
28963     
28964     focusCls: 'focus',
28965
28966     
28967     menuActiveCls: 'menu-active',
28968
28969     
28970
28971     
28972
28973     
28974
28975     ariaRole: 'button',
28976
28977     
28978     renderTpl:
28979         '<em id="{id}-btnWrap" class="{splitCls}">' +
28980             '<tpl if="href">' +
28981                 '<a id="{id}-btnEl" href="{href}" target="{target}"<tpl if="tabIndex"> tabIndex="{tabIndex}"</tpl> role="link">' +
28982                     '<span id="{id}-btnInnerEl" class="{baseCls}-inner">' +
28983                         '{text}' +
28984                     '</span>' +
28985                         '<span id="{id}-btnIconEl" class="{baseCls}-icon"></span>' +
28986                 '</a>' +
28987             '</tpl>' +
28988             '<tpl if="!href">' +
28989                 '<button id="{id}-btnEl" type="{type}" hidefocus="true"' +
28990                     
28991                     
28992                     '<tpl if="tabIndex"> tabIndex="{tabIndex}"</tpl> role="button" autocomplete="off">' +
28993                     '<span id="{id}-btnInnerEl" class="{baseCls}-inner" style="{innerSpanStyle}">' +
28994                         '{text}' +
28995                     '</span>' +
28996                     '<span id="{id}-btnIconEl" class="{baseCls}-icon {iconCls}">&#160;</span>' +
28997                 '</button>' +
28998             '</tpl>' +
28999         '</em>' ,
29000
29001     
29002     scale: 'small',
29003
29004     
29005     allowedScales: ['small', 'medium', 'large'],
29006
29007     
29008
29009     
29010     iconAlign: 'left',
29011
29012     
29013     arrowAlign: 'right',
29014
29015     
29016     arrowCls: 'arrow',
29017
29018     
29019
29020     
29021
29022     
29023
29024     
29025
29026     maskOnDisable: false,
29027
29028     
29029     initComponent: function() {
29030         var me = this;
29031         me.callParent(arguments);
29032
29033         me.addEvents(
29034             
29035             'click',
29036
29037             
29038             'toggle',
29039
29040             
29041             'mouseover',
29042
29043             
29044             'mouseout',
29045
29046             
29047             'menushow',
29048
29049             
29050             'menuhide',
29051
29052             
29053             'menutriggerover',
29054
29055             
29056             'menutriggerout'
29057         );
29058
29059         if (me.menu) {
29060             
29061             me.split = true;
29062
29063             
29064             me.menu = Ext.menu.Manager.get(me.menu);
29065             me.menu.ownerCt = me;
29066         }
29067
29068         
29069         if (me.url) {
29070             me.href = me.url;
29071         }
29072
29073         
29074         if (me.href && !me.hasOwnProperty('preventDefault')) {
29075             me.preventDefault = false;
29076         }
29077
29078         if (Ext.isString(me.toggleGroup)) {
29079             me.enableToggle = true;
29080         }
29081
29082     },
29083
29084     
29085     initAria: function() {
29086         this.callParent();
29087         var actionEl = this.getActionEl();
29088         if (this.menu) {
29089             actionEl.dom.setAttribute('aria-haspopup', true);
29090         }
29091     },
29092
29093     
29094     getActionEl: function() {
29095         return this.btnEl;
29096     },
29097
29098     
29099     getFocusEl: function() {
29100         return this.btnEl;
29101     },
29102
29103     
29104     setButtonCls: function() {
29105         var me = this,
29106             cls = [],
29107             btnIconEl = me.btnIconEl,
29108             hide = 'x-hide-display';
29109
29110         if (me.useSetClass) {
29111             if (!Ext.isEmpty(me.oldCls)) {
29112                 me.removeClsWithUI(me.oldCls);
29113                 me.removeClsWithUI(me.pressedCls);
29114             }
29115
29116             
29117             if (me.iconCls || me.icon) {
29118                 if (me.text) {
29119                     cls.push('icon-text-' + me.iconAlign);
29120                 } else {
29121                     cls.push('icon');
29122                 }
29123                 if (btnIconEl) {
29124                     btnIconEl.removeCls(hide);
29125                 }
29126             } else {
29127                 if (me.text) {
29128                     cls.push('noicon');
29129                 }
29130                 if (btnIconEl) {
29131                     btnIconEl.addCls(hide);
29132                 }
29133             }
29134
29135             me.oldCls = cls;
29136             me.addClsWithUI(cls);
29137             me.addClsWithUI(me.pressed ? me.pressedCls : null);
29138         }
29139     },
29140
29141     
29142     onRender: function(ct, position) {
29143         
29144         var me = this,
29145             repeater, btn;
29146
29147         
29148         Ext.applyIf(me.renderData, me.getTemplateArgs());
29149
29150         me.addChildEls('btnEl', 'btnWrap', 'btnInnerEl', 'btnIconEl');
29151
29152         if (me.scale) {
29153             me.ui = me.ui + '-' + me.scale;
29154         }
29155
29156         
29157         me.callParent(arguments);
29158
29159         
29160         if (me.split && me.arrowTooltip) {
29161             me.arrowEl.dom.setAttribute(me.getTipAttr(), me.arrowTooltip);
29162         }
29163
29164         
29165         me.mon(me.btnEl, {
29166             scope: me,
29167             focus: me.onFocus,
29168             blur : me.onBlur
29169         });
29170
29171         
29172         btn = me.el;
29173
29174         if (me.icon) {
29175             me.setIcon(me.icon);
29176         }
29177
29178         if (me.iconCls) {
29179             me.setIconCls(me.iconCls);
29180         }
29181
29182         if (me.tooltip) {
29183             me.setTooltip(me.tooltip, true);
29184         }
29185
29186         if (me.textAlign) {
29187             me.setTextAlign(me.textAlign);
29188         }
29189
29190         
29191         if (me.handleMouseEvents) {
29192             me.mon(btn, {
29193                 scope: me,
29194                 mouseover: me.onMouseOver,
29195                 mouseout: me.onMouseOut,
29196                 mousedown: me.onMouseDown
29197             });
29198
29199             if (me.split) {
29200                 me.mon(btn, {
29201                     mousemove: me.onMouseMove,
29202                     scope: me
29203                 });
29204             }
29205         }
29206
29207         
29208         if (me.menu) {
29209             me.mon(me.menu, {
29210                 scope: me,
29211                 show: me.onMenuShow,
29212                 hide: me.onMenuHide
29213             });
29214
29215             me.keyMap = Ext.create('Ext.util.KeyMap', me.el, {
29216                 key: Ext.EventObject.DOWN,
29217                 handler: me.onDownKey,
29218                 scope: me
29219             });
29220         }
29221
29222         
29223         if (me.repeat) {
29224             repeater = Ext.create('Ext.util.ClickRepeater', btn, Ext.isObject(me.repeat) ? me.repeat: {});
29225             me.mon(repeater, 'click', me.onRepeatClick, me);
29226         } else {
29227             me.mon(btn, me.clickEvent, me.onClick, me);
29228         }
29229
29230         
29231         Ext.ButtonToggleManager.register(me);
29232     },
29233
29234     
29235     getTemplateArgs: function() {
29236         var me = this,
29237             persistentPadding = me.getPersistentBtnPadding(),
29238             innerSpanStyle = '';
29239
29240         
29241         if (Math.max.apply(Math, persistentPadding) > 0) {
29242             innerSpanStyle = 'margin:' + Ext.Array.map(persistentPadding, function(pad) {
29243                 return -pad + 'px';
29244             }).join(' ');
29245         }
29246
29247         return {
29248             href     : me.getHref(),
29249             target   : me.target || '_blank',
29250             type     : me.type,
29251             splitCls : me.getSplitCls(),
29252             cls      : me.cls,
29253             iconCls  : me.iconCls || '',
29254             text     : me.text || '&#160;',
29255             tabIndex : me.tabIndex,
29256             innerSpanStyle: innerSpanStyle
29257         };
29258     },
29259
29260     
29261     getHref: function() {
29262         var me = this,
29263             params = Ext.apply({}, me.baseParams);
29264
29265         
29266         params = Ext.apply(params, me.params);
29267         return me.href ? Ext.urlAppend(me.href, Ext.Object.toQueryString(params)) : false;
29268     },
29269
29270     
29271     setParams: function(params) {
29272         this.params = params;
29273         this.btnEl.dom.href = this.getHref();
29274     },
29275
29276     getSplitCls: function() {
29277         var me = this;
29278         return me.split ? (me.baseCls + '-' + me.arrowCls) + ' ' + (me.baseCls + '-' + me.arrowCls + '-' + me.arrowAlign) : '';
29279     },
29280
29281     
29282     afterRender: function() {
29283         var me = this;
29284         me.useSetClass = true;
29285         me.setButtonCls();
29286         me.doc = Ext.getDoc();
29287         this.callParent(arguments);
29288     },
29289
29290     
29291     setIconCls: function(cls) {
29292         var me = this,
29293             btnIconEl = me.btnIconEl,
29294             oldCls = me.iconCls;
29295             
29296         me.iconCls = cls;
29297         if (btnIconEl) {
29298             
29299             btnIconEl.removeCls(oldCls);
29300             btnIconEl.addCls(cls || '');
29301             me.setButtonCls();
29302         }
29303         return me;
29304     },
29305
29306     
29307     setTooltip: function(tooltip, initial) {
29308         var me = this;
29309
29310         if (me.rendered) {
29311             if (!initial) {
29312                 me.clearTip();
29313             }
29314             if (Ext.isObject(tooltip)) {
29315                 Ext.tip.QuickTipManager.register(Ext.apply({
29316                     target: me.btnEl.id
29317                 },
29318                 tooltip));
29319                 me.tooltip = tooltip;
29320             } else {
29321                 me.btnEl.dom.setAttribute(me.getTipAttr(), tooltip);
29322             }
29323         } else {
29324             me.tooltip = tooltip;
29325         }
29326         return me;
29327     },
29328
29329     
29330     setTextAlign: function(align) {
29331         var me = this,
29332             btnEl = me.btnEl;
29333
29334         if (btnEl) {
29335             btnEl.removeCls(me.baseCls + '-' + me.textAlign);
29336             btnEl.addCls(me.baseCls + '-' + align);
29337         }
29338         me.textAlign = align;
29339         return me;
29340     },
29341
29342     getTipAttr: function(){
29343         return this.tooltipType == 'qtip' ? 'data-qtip' : 'title';
29344     },
29345
29346     
29347     getRefItems: function(deep){
29348         var menu = this.menu,
29349             items;
29350         
29351         if (menu) {
29352             items = menu.getRefItems(deep);
29353             items.unshift(menu);
29354         }
29355         return items || [];
29356     },
29357
29358     
29359     clearTip: function() {
29360         if (Ext.isObject(this.tooltip)) {
29361             Ext.tip.QuickTipManager.unregister(this.btnEl);
29362         }
29363     },
29364
29365     
29366     beforeDestroy: function() {
29367         var me = this;
29368         if (me.rendered) {
29369             me.clearTip();
29370         }
29371         if (me.menu && me.destroyMenu !== false) {
29372             Ext.destroy(me.menu);
29373         }
29374         Ext.destroy(me.btnInnerEl, me.repeater);
29375         me.callParent();
29376     },
29377
29378     
29379     onDestroy: function() {
29380         var me = this;
29381         if (me.rendered) {
29382             me.doc.un('mouseover', me.monitorMouseOver, me);
29383             me.doc.un('mouseup', me.onMouseUp, me);
29384             delete me.doc;
29385             Ext.ButtonToggleManager.unregister(me);
29386
29387             Ext.destroy(me.keyMap);
29388             delete me.keyMap;
29389         }
29390         me.callParent();
29391     },
29392
29393     
29394     setHandler: function(handler, scope) {
29395         this.handler = handler;
29396         this.scope = scope;
29397         return this;
29398     },
29399
29400     
29401     setText: function(text) {
29402         var me = this;
29403         me.text = text;
29404         if (me.el) {
29405             me.btnInnerEl.update(text || '&#160;');
29406             me.setButtonCls();
29407         }
29408         me.doComponentLayout();
29409         return me;
29410     },
29411
29412     
29413     setIcon: function(icon) {
29414         var me = this,
29415             iconEl = me.btnIconEl;
29416             
29417         me.icon = icon;
29418         if (iconEl) {
29419             iconEl.setStyle('background-image', icon ? 'url(' + icon + ')': '');
29420             me.setButtonCls();
29421         }
29422         return me;
29423     },
29424
29425     
29426     getText: function() {
29427         return this.text;
29428     },
29429
29430     
29431     toggle: function(state, suppressEvent) {
29432         var me = this;
29433         state = state === undefined ? !me.pressed : !!state;
29434         if (state !== me.pressed) {
29435             if (me.rendered) {
29436                 me[state ? 'addClsWithUI': 'removeClsWithUI'](me.pressedCls);
29437             }
29438             me.btnEl.dom.setAttribute('aria-pressed', state);
29439             me.pressed = state;
29440             if (!suppressEvent) {
29441                 me.fireEvent('toggle', me, state);
29442                 Ext.callback(me.toggleHandler, me.scope || me, [me, state]);
29443             }
29444         }
29445         return me;
29446     },
29447     
29448     maybeShowMenu: function(){
29449         var me = this;
29450         if (me.menu && !me.hasVisibleMenu() && !me.ignoreNextClick) {
29451             me.showMenu();
29452         }
29453     },
29454
29455     
29456     showMenu: function() {
29457         var me = this;
29458         if (me.rendered && me.menu) {
29459             if (me.tooltip && me.getTipAttr() != 'title') {
29460                 Ext.tip.QuickTipManager.getQuickTip().cancelShow(me.btnEl);
29461             }
29462             if (me.menu.isVisible()) {
29463                 me.menu.hide();
29464             }
29465
29466             me.menu.showBy(me.el, me.menuAlign);
29467         }
29468         return me;
29469     },
29470
29471     
29472     hideMenu: function() {
29473         if (this.hasVisibleMenu()) {
29474             this.menu.hide();
29475         }
29476         return this;
29477     },
29478
29479     
29480     hasVisibleMenu: function() {
29481         var menu = this.menu;
29482         return menu && menu.rendered && menu.isVisible();
29483     },
29484
29485     
29486     onRepeatClick: function(repeat, e) {
29487         this.onClick(e);
29488     },
29489
29490     
29491     onClick: function(e) {
29492         var me = this;
29493         if (me.preventDefault || (me.disabled && me.getHref()) && e) {
29494             e.preventDefault();
29495         }
29496         if (e.button !== 0) {
29497             return;
29498         }
29499         if (!me.disabled) {
29500             me.doToggle();
29501             me.maybeShowMenu();
29502             me.fireHandler(e);
29503         }
29504     },
29505     
29506     fireHandler: function(e){
29507         var me = this,
29508             handler = me.handler;
29509             
29510         me.fireEvent('click', me, e);
29511         if (handler) {
29512             handler.call(me.scope || me, me, e);
29513         }
29514         me.onBlur();
29515     },
29516     
29517     doToggle: function(){
29518         var me = this;
29519         if (me.enableToggle && (me.allowDepress !== false || !me.pressed)) {
29520             me.toggle();
29521         }
29522     },
29523
29524     
29525     onMouseOver: function(e) {
29526         var me = this;
29527         if (!me.disabled && !e.within(me.el, true, true)) {
29528             me.onMouseEnter(e);
29529         }
29530     },
29531
29532     
29533     onMouseOut: function(e) {
29534         var me = this;
29535         if (!e.within(me.el, true, true)) {
29536             if (me.overMenuTrigger) {
29537                 me.onMenuTriggerOut(e);
29538             }
29539             me.onMouseLeave(e);
29540         }
29541     },
29542
29543     
29544     onMouseMove: function(e) {
29545         var me = this,
29546             el = me.el,
29547             over = me.overMenuTrigger,
29548             overlap, btnSize;
29549
29550         if (me.split) {
29551             if (me.arrowAlign === 'right') {
29552                 overlap = e.getX() - el.getX();
29553                 btnSize = el.getWidth();
29554             } else {
29555                 overlap = e.getY() - el.getY();
29556                 btnSize = el.getHeight();
29557             }
29558
29559             if (overlap > (btnSize - me.getTriggerSize())) {
29560                 if (!over) {
29561                     me.onMenuTriggerOver(e);
29562                 }
29563             } else {
29564                 if (over) {
29565                     me.onMenuTriggerOut(e);
29566                 }
29567             }
29568         }
29569     },
29570
29571     
29572     getTriggerSize: function() {
29573         var me = this,
29574             size = me.triggerSize,
29575             side, sideFirstLetter, undef;
29576
29577         if (size === undef) {
29578             side = me.arrowAlign;
29579             sideFirstLetter = side.charAt(0);
29580             size = me.triggerSize = me.el.getFrameWidth(sideFirstLetter) + me.btnWrap.getFrameWidth(sideFirstLetter) + (me.frameSize && me.frameSize[side] || 0);
29581         }
29582         return size;
29583     },
29584
29585     
29586     onMouseEnter: function(e) {
29587         var me = this;
29588         me.addClsWithUI(me.overCls);
29589         me.fireEvent('mouseover', me, e);
29590     },
29591
29592     
29593     onMouseLeave: function(e) {
29594         var me = this;
29595         me.removeClsWithUI(me.overCls);
29596         me.fireEvent('mouseout', me, e);
29597     },
29598
29599     
29600     onMenuTriggerOver: function(e) {
29601         var me = this;
29602         me.overMenuTrigger = true;
29603         me.fireEvent('menutriggerover', me, me.menu, e);
29604     },
29605
29606     
29607     onMenuTriggerOut: function(e) {
29608         var me = this;
29609         delete me.overMenuTrigger;
29610         me.fireEvent('menutriggerout', me, me.menu, e);
29611     },
29612
29613     
29614     enable : function(silent) {
29615         var me = this;
29616
29617         me.callParent(arguments);
29618
29619         me.removeClsWithUI('disabled');
29620
29621         return me;
29622     },
29623
29624     
29625     disable : function(silent) {
29626         var me = this;
29627
29628         me.callParent(arguments);
29629
29630         me.addClsWithUI('disabled');
29631         me.removeClsWithUI(me.overCls);
29632
29633         return me;
29634     },
29635
29636     
29637     setScale: function(scale) {
29638         var me = this,
29639             ui = me.ui.replace('-' + me.scale, '');
29640
29641         
29642         if (!Ext.Array.contains(me.allowedScales, scale)) {
29643             throw('#setScale: scale must be an allowed scale (' + me.allowedScales.join(', ') + ')');
29644         }
29645
29646         me.scale = scale;
29647         me.setUI(ui);
29648     },
29649
29650     
29651     setUI: function(ui) {
29652         var me = this;
29653
29654         
29655         if (me.scale && !ui.match(me.scale)) {
29656             ui = ui + '-' + me.scale;
29657         }
29658
29659         me.callParent([ui]);
29660
29661         
29662         
29663     },
29664
29665     
29666     onFocus: function(e) {
29667         var me = this;
29668         if (!me.disabled) {
29669             me.addClsWithUI(me.focusCls);
29670         }
29671     },
29672
29673     
29674     onBlur: function(e) {
29675         var me = this;
29676         me.removeClsWithUI(me.focusCls);
29677     },
29678
29679     
29680     onMouseDown: function(e) {
29681         var me = this;
29682         if (!me.disabled && e.button === 0) {
29683             me.addClsWithUI(me.pressedCls);
29684             me.doc.on('mouseup', me.onMouseUp, me);
29685         }
29686     },
29687     
29688     onMouseUp: function(e) {
29689         var me = this;
29690         if (e.button === 0) {
29691             if (!me.pressed) {
29692                 me.removeClsWithUI(me.pressedCls);
29693             }
29694             me.doc.un('mouseup', me.onMouseUp, me);
29695         }
29696     },
29697     
29698     onMenuShow: function(e) {
29699         var me = this;
29700         me.ignoreNextClick = 0;
29701         me.addClsWithUI(me.menuActiveCls);
29702         me.fireEvent('menushow', me, me.menu);
29703     },
29704
29705     
29706     onMenuHide: function(e) {
29707         var me = this;
29708         me.removeClsWithUI(me.menuActiveCls);
29709         me.ignoreNextClick = Ext.defer(me.restoreClick, 250, me);
29710         me.fireEvent('menuhide', me, me.menu);
29711     },
29712
29713     
29714     restoreClick: function() {
29715         this.ignoreNextClick = 0;
29716     },
29717
29718     
29719     onDownKey: function() {
29720         var me = this;
29721
29722         if (!me.disabled) {
29723             if (me.menu) {
29724                 me.showMenu();
29725             }
29726         }
29727     },
29728
29729     
29730     getPersistentBtnPadding: function() {
29731         var cls = Ext.button.Button,
29732             padding = cls.persistentPadding,
29733             btn, leftTop, btnEl, btnInnerEl;
29734
29735         if (!padding) {
29736             padding = cls.persistentPadding = [0, 0, 0, 0]; 
29737
29738             if (!Ext.isIE) { 
29739                 
29740                 btn = Ext.create('Ext.button.Button', {
29741                     renderTo: Ext.getBody(),
29742                     text: 'test',
29743                     style: 'position:absolute;top:-999px;'
29744                 });
29745                 btnEl = btn.btnEl;
29746                 btnInnerEl = btn.btnInnerEl;
29747                 btnEl.setSize(null, null); 
29748
29749                 leftTop = btnInnerEl.getOffsetsTo(btnEl);
29750                 padding[0] = leftTop[1];
29751                 padding[1] = btnEl.getWidth() - btnInnerEl.getWidth() - leftTop[0];
29752                 padding[2] = btnEl.getHeight() - btnInnerEl.getHeight() - leftTop[1];
29753                 padding[3] = leftTop[0];
29754
29755                 btn.destroy();
29756             }
29757         }
29758
29759         return padding;
29760     }
29761
29762 }, function() {
29763     var groups = {};
29764
29765     function toggleGroup(btn, state) {
29766         var g, i, l;
29767         if (state) {
29768             g = groups[btn.toggleGroup];
29769             for (i = 0, l = g.length; i < l; i++) {
29770                 if (g[i] !== btn) {
29771                     g[i].toggle(false);
29772                 }
29773             }
29774         }
29775     }
29776
29777     
29778     Ext.ButtonToggleManager = {
29779         register: function(btn) {
29780             if (!btn.toggleGroup) {
29781                 return;
29782             }
29783             var group = groups[btn.toggleGroup];
29784             if (!group) {
29785                 group = groups[btn.toggleGroup] = [];
29786             }
29787             group.push(btn);
29788             btn.on('toggle', toggleGroup);
29789         },
29790
29791         unregister: function(btn) {
29792             if (!btn.toggleGroup) {
29793                 return;
29794             }
29795             var group = groups[btn.toggleGroup];
29796             if (group) {
29797                 Ext.Array.remove(group, btn);
29798                 btn.un('toggle', toggleGroup);
29799             }
29800         },
29801
29802         
29803         getPressed: function(group) {
29804             var g = groups[group],
29805                 i = 0,
29806                 len;
29807             if (g) {
29808                 for (len = g.length; i < len; i++) {
29809                     if (g[i].pressed === true) {
29810                         return g[i];
29811                     }
29812                 }
29813             }
29814             return null;
29815         }
29816     };
29817 });
29818
29819
29820 Ext.define('Ext.layout.container.boxOverflow.Menu', {
29821
29822     
29823
29824     extend: 'Ext.layout.container.boxOverflow.None',
29825     requires: ['Ext.toolbar.Separator', 'Ext.button.Button'],
29826     alternateClassName: 'Ext.layout.boxOverflow.Menu',
29827     
29828     
29829
29830     
29831
29832     
29833     noItemsMenuText : '<div class="' + Ext.baseCSSPrefix + 'toolbar-no-items">(None)</div>',
29834
29835     constructor: function(layout) {
29836         var me = this;
29837
29838         me.callParent(arguments);
29839
29840         
29841         layout.beforeLayout = Ext.Function.createInterceptor(layout.beforeLayout, this.clearOverflow, this);
29842
29843         me.afterCtCls = me.afterCtCls || Ext.baseCSSPrefix + 'box-menu-' + layout.parallelAfter;
29844         
29845         me.menuItems = [];
29846     },
29847     
29848     onRemove: function(comp){
29849         Ext.Array.remove(this.menuItems, comp);
29850     },
29851
29852     handleOverflow: function(calculations, targetSize) {
29853         var me = this,
29854             layout = me.layout,
29855             methodName = 'get' + layout.parallelPrefixCap,
29856             newSize = {},
29857             posArgs = [null, null];
29858
29859         me.callParent(arguments);
29860         this.createMenu(calculations, targetSize);
29861         newSize[layout.perpendicularPrefix] = targetSize[layout.perpendicularPrefix];
29862         newSize[layout.parallelPrefix] = targetSize[layout.parallelPrefix] - me.afterCt[methodName]();
29863
29864         
29865         
29866         posArgs[layout.perpendicularSizeIndex] = (calculations.meta.maxSize - me.menuTrigger['get' + layout.perpendicularPrefixCap]()) / 2;
29867         me.menuTrigger.setPosition.apply(me.menuTrigger, posArgs);
29868
29869         return { targetSize: newSize };
29870     },
29871
29872     
29873     clearOverflow: function(calculations, targetSize) {
29874         var me = this,
29875             newWidth = targetSize ? targetSize.width + (me.afterCt ? me.afterCt.getWidth() : 0) : 0,
29876             items = me.menuItems,
29877             i = 0,
29878             length = items.length,
29879             item;
29880
29881         me.hideTrigger();
29882         for (; i < length; i++) {
29883             items[i].show();
29884         }
29885         items.length = 0;
29886
29887         return targetSize ? {
29888             targetSize: {
29889                 height: targetSize.height,
29890                 width : newWidth
29891             }
29892         } : null;
29893     },
29894
29895     
29896     showTrigger: function() {
29897         this.menuTrigger.show();
29898     },
29899
29900     
29901     hideTrigger: function() {
29902         if (this.menuTrigger !== undefined) {
29903             this.menuTrigger.hide();
29904         }
29905     },
29906
29907     
29908     beforeMenuShow: function(menu) {
29909         var me = this,
29910             items = me.menuItems,
29911             i = 0,
29912             len   = items.length,
29913             item,
29914             prev;
29915
29916         var needsSep = function(group, prev){
29917             return group.isXType('buttongroup') && !(prev instanceof Ext.toolbar.Separator);
29918         };
29919
29920         me.clearMenu();
29921         menu.removeAll();
29922
29923         for (; i < len; i++) {
29924             item = items[i];
29925
29926             
29927             if (!i && (item instanceof Ext.toolbar.Separator)) {
29928                 continue;
29929             }
29930             if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
29931                 menu.add('-');
29932             }
29933
29934             me.addComponentToMenu(menu, item);
29935             prev = item;
29936         }
29937
29938         
29939         if (menu.items.length < 1) {
29940             menu.add(me.noItemsMenuText);
29941         }
29942     },
29943     
29944     
29945     createMenuConfig : function(component, hideOnClick) {
29946         var config = Ext.apply({}, component.initialConfig),
29947             group  = component.toggleGroup;
29948
29949         Ext.copyTo(config, component, [
29950             'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
29951         ]);
29952
29953         Ext.apply(config, {
29954             text       : component.overflowText || component.text,
29955             hideOnClick: hideOnClick,
29956             destroyMenu: false
29957         });
29958
29959         if (group || component.enableToggle) {
29960             Ext.apply(config, {
29961                 group  : group,
29962                 checked: component.pressed,
29963                 listeners: {
29964                     checkchange: function(item, checked){
29965                         component.toggle(checked);
29966                     }
29967                 }
29968             });
29969         }
29970
29971         delete config.ownerCt;
29972         delete config.xtype;
29973         delete config.id;
29974         return config;
29975     },
29976
29977     
29978     addComponentToMenu : function(menu, component) {
29979         var me = this;
29980         if (component instanceof Ext.toolbar.Separator) {
29981             menu.add('-');
29982         } else if (component.isComponent) {
29983             if (component.isXType('splitbutton')) {
29984                 menu.add(me.createMenuConfig(component, true));
29985
29986             } else if (component.isXType('button')) {
29987                 menu.add(me.createMenuConfig(component, !component.menu));
29988
29989             } else if (component.isXType('buttongroup')) {
29990                 component.items.each(function(item){
29991                      me.addComponentToMenu(menu, item);
29992                 });
29993             } else {
29994                 menu.add(Ext.create(Ext.getClassName(component), me.createMenuConfig(component)));
29995             }
29996         }
29997     },
29998
29999     
30000     clearMenu : function() {
30001         var menu = this.moreMenu;
30002         if (menu && menu.items) {
30003             menu.items.each(function(item) {
30004                 if (item.menu) {
30005                     delete item.menu;
30006                 }
30007             });
30008         }
30009     },
30010
30011     
30012     createMenu: function(calculations, targetSize) {
30013         var me = this,
30014             layout = me.layout,
30015             startProp = layout.parallelBefore,
30016             sizeProp = layout.parallelPrefix,
30017             available = targetSize[sizeProp],
30018             boxes = calculations.boxes,
30019             i = 0,
30020             len = boxes.length,
30021             box;
30022
30023         if (!me.menuTrigger) {
30024             me.createInnerElements();
30025
30026             
30027             me.menu = Ext.create('Ext.menu.Menu', {
30028                 listeners: {
30029                     scope: me,
30030                     beforeshow: me.beforeMenuShow
30031                 }
30032             });
30033
30034             
30035             me.menuTrigger = Ext.create('Ext.button.Button', {
30036                 ownerCt : me.layout.owner, 
30037                 iconCls : me.layout.owner.menuTriggerCls,
30038                 ui      : layout.owner instanceof Ext.toolbar.Toolbar ? 'default-toolbar' : 'default',
30039                 menu    : me.menu,
30040                 getSplitCls: function() { return '';},
30041                 renderTo: me.afterCt
30042             });
30043         }
30044         me.showTrigger();
30045         available -= me.afterCt.getWidth();
30046
30047         
30048         
30049         me.menuItems.length = 0;
30050         for (; i < len; i++) {
30051             box = boxes[i];
30052             if (box[startProp] + box[sizeProp] > available) {
30053                 me.menuItems.push(box.component);
30054                 box.component.hide();
30055             }
30056         }
30057     },
30058
30059     
30060     createInnerElements: function() {
30061         var me = this,
30062             target = me.layout.getRenderTarget();
30063
30064         if (!this.afterCt) {
30065             target.addCls(Ext.baseCSSPrefix + me.layout.direction + '-box-overflow-body');
30066             this.afterCt  = target.insertSibling({cls: Ext.layout.container.Box.prototype.innerCls + ' ' + this.afterCtCls}, 'before');
30067         }
30068     },
30069
30070     
30071     destroy: function() {
30072         Ext.destroy(this.menu, this.menuTrigger);
30073     }
30074 });
30075
30076 Ext.define('Ext.util.Region', {
30077
30078     
30079
30080     requires: ['Ext.util.Offset'],
30081
30082     statics: {
30083         
30084         getRegion: function(el) {
30085             return Ext.fly(el).getPageBox(true);
30086         },
30087
30088         
30089         from: function(o) {
30090             return new this(o.top, o.right, o.bottom, o.left);
30091         }
30092     },
30093
30094     
30095
30096     
30097     constructor : function(t, r, b, l) {
30098         var me = this;
30099         me.y = me.top = me[1] = t;
30100         me.right = r;
30101         me.bottom = b;
30102         me.x = me.left = me[0] = l;
30103     },
30104
30105     
30106     contains : function(region) {
30107         var me = this;
30108         return (region.x >= me.x &&
30109                 region.right <= me.right &&
30110                 region.y >= me.y &&
30111                 region.bottom <= me.bottom);
30112
30113     },
30114
30115     
30116     intersect : function(region) {
30117         var me = this,
30118             t = Math.max(me.y, region.y),
30119             r = Math.min(me.right, region.right),
30120             b = Math.min(me.bottom, region.bottom),
30121             l = Math.max(me.x, region.x);
30122
30123         if (b > t && r > l) {
30124             return new this.self(t, r, b, l);
30125         }
30126         else {
30127             return false;
30128         }
30129     },
30130
30131     
30132     union : function(region) {
30133         var me = this,
30134             t = Math.min(me.y, region.y),
30135             r = Math.max(me.right, region.right),
30136             b = Math.max(me.bottom, region.bottom),
30137             l = Math.min(me.x, region.x);
30138
30139         return new this.self(t, r, b, l);
30140     },
30141
30142     
30143     constrainTo : function(r) {
30144         var me = this,
30145             constrain = Ext.Number.constrain;
30146         me.top = me.y = constrain(me.top, r.y, r.bottom);
30147         me.bottom = constrain(me.bottom, r.y, r.bottom);
30148         me.left = me.x = constrain(me.left, r.x, r.right);
30149         me.right = constrain(me.right, r.x, r.right);
30150         return me;
30151     },
30152
30153     
30154     adjust : function(t, r, b, l) {
30155         var me = this;
30156         me.top = me.y += t;
30157         me.left = me.x += l;
30158         me.right += r;
30159         me.bottom += b;
30160         return me;
30161     },
30162
30163     
30164     getOutOfBoundOffset: function(axis, p) {
30165         if (!Ext.isObject(axis)) {
30166             if (axis == 'x') {
30167                 return this.getOutOfBoundOffsetX(p);
30168             } else {
30169                 return this.getOutOfBoundOffsetY(p);
30170             }
30171         } else {
30172             p = axis;
30173             var d = Ext.create('Ext.util.Offset');
30174             d.x = this.getOutOfBoundOffsetX(p.x);
30175             d.y = this.getOutOfBoundOffsetY(p.y);
30176             return d;
30177         }
30178
30179     },
30180
30181     
30182     getOutOfBoundOffsetX: function(p) {
30183         if (p <= this.x) {
30184             return this.x - p;
30185         } else if (p >= this.right) {
30186             return this.right - p;
30187         }
30188
30189         return 0;
30190     },
30191
30192     
30193     getOutOfBoundOffsetY: function(p) {
30194         if (p <= this.y) {
30195             return this.y - p;
30196         } else if (p >= this.bottom) {
30197             return this.bottom - p;
30198         }
30199
30200         return 0;
30201     },
30202
30203     
30204     isOutOfBound: function(axis, p) {
30205         if (!Ext.isObject(axis)) {
30206             if (axis == 'x') {
30207                 return this.isOutOfBoundX(p);
30208             } else {
30209                 return this.isOutOfBoundY(p);
30210             }
30211         } else {
30212             p = axis;
30213             return (this.isOutOfBoundX(p.x) || this.isOutOfBoundY(p.y));
30214         }
30215     },
30216
30217     
30218     isOutOfBoundX: function(p) {
30219         return (p < this.x || p > this.right);
30220     },
30221
30222     
30223     isOutOfBoundY: function(p) {
30224         return (p < this.y || p > this.bottom);
30225     },
30226
30227     
30228     restrict: function(axis, p, factor) {
30229         if (Ext.isObject(axis)) {
30230             var newP;
30231
30232             factor = p;
30233             p = axis;
30234
30235             if (p.copy) {
30236                 newP = p.copy();
30237             }
30238             else {
30239                 newP = {
30240                     x: p.x,
30241                     y: p.y
30242                 };
30243             }
30244
30245             newP.x = this.restrictX(p.x, factor);
30246             newP.y = this.restrictY(p.y, factor);
30247             return newP;
30248         } else {
30249             if (axis == 'x') {
30250                 return this.restrictX(p, factor);
30251             } else {
30252                 return this.restrictY(p, factor);
30253             }
30254         }
30255     },
30256
30257     
30258     restrictX : function(p, factor) {
30259         if (!factor) {
30260             factor = 1;
30261         }
30262
30263         if (p <= this.x) {
30264             p -= (p - this.x) * factor;
30265         }
30266         else if (p >= this.right) {
30267             p -= (p - this.right) * factor;
30268         }
30269         return p;
30270     },
30271
30272     
30273     restrictY : function(p, factor) {
30274         if (!factor) {
30275             factor = 1;
30276         }
30277
30278         if (p <= this.y) {
30279             p -= (p - this.y) * factor;
30280         }
30281         else if (p >= this.bottom) {
30282             p -= (p - this.bottom) * factor;
30283         }
30284         return p;
30285     },
30286
30287     
30288     getSize: function() {
30289         return {
30290             width: this.right - this.x,
30291             height: this.bottom - this.y
30292         };
30293     },
30294
30295     
30296     copy: function() {
30297         return new this.self(this.y, this.right, this.bottom, this.x);
30298     },
30299
30300     
30301     copyFrom: function(p) {
30302         var me = this;
30303         me.top = me.y = me[1] = p.y;
30304         me.right = p.right;
30305         me.bottom = p.bottom;
30306         me.left = me.x = me[0] = p.x;
30307
30308         return this;
30309     },
30310
30311     
30312     toString: function() {
30313         return "Region[" + this.top + "," + this.right + "," + this.bottom + "," + this.left + "]";
30314     },
30315
30316     
30317     translateBy: function(x, y) {
30318         if (arguments.length == 1) {
30319             y = x.y;
30320             x = x.x;
30321         }
30322         var me = this;
30323         me.top = me.y += y;
30324         me.right += x;
30325         me.bottom += y;
30326         me.left = me.x += x;
30327
30328         return me;
30329     },
30330
30331     
30332     round: function() {
30333         var me = this;
30334         me.top = me.y = Math.round(me.y);
30335         me.right = Math.round(me.right);
30336         me.bottom = Math.round(me.bottom);
30337         me.left = me.x = Math.round(me.x);
30338
30339         return me;
30340     },
30341
30342     
30343     equals: function(region) {
30344         return (this.top == region.top && this.right == region.right && this.bottom == region.bottom && this.left == region.left);
30345     }
30346 });
30347
30348
30349
30350
30351
30352 Ext.define('Ext.dd.DragDropManager', {
30353     singleton: true,
30354
30355     requires: ['Ext.util.Region'],
30356
30357     uses: ['Ext.tip.QuickTipManager'],
30358
30359     
30360     alternateClassName: ['Ext.dd.DragDropMgr', 'Ext.dd.DDM'],
30361
30362     
30363     ids: {},
30364
30365     
30366     handleIds: {},
30367
30368     
30369     dragCurrent: null,
30370
30371     
30372     dragOvers: {},
30373
30374     
30375     deltaX: 0,
30376
30377     
30378     deltaY: 0,
30379
30380     
30381     preventDefault: true,
30382
30383     
30384     stopPropagation: true,
30385
30386     
30387     initialized: false,
30388
30389     
30390     locked: false,
30391
30392     
30393     init: function() {
30394         this.initialized = true;
30395     },
30396
30397     
30398     POINT: 0,
30399
30400     
30401     INTERSECT: 1,
30402
30403     
30404     mode: 0,
30405
30406     
30407     _execOnAll: function(sMethod, args) {
30408         for (var i in this.ids) {
30409             for (var j in this.ids[i]) {
30410                 var oDD = this.ids[i][j];
30411                 if (! this.isTypeOfDD(oDD)) {
30412                     continue;
30413                 }
30414                 oDD[sMethod].apply(oDD, args);
30415             }
30416         }
30417     },
30418
30419     
30420     _onLoad: function() {
30421
30422         this.init();
30423
30424         var Event = Ext.EventManager;
30425         Event.on(document, "mouseup",   this.handleMouseUp, this, true);
30426         Event.on(document, "mousemove", this.handleMouseMove, this, true);
30427         Event.on(window,   "unload",    this._onUnload, this, true);
30428         Event.on(window,   "resize",    this._onResize, this, true);
30429         
30430
30431     },
30432
30433     
30434     _onResize: function(e) {
30435         this._execOnAll("resetConstraints", []);
30436     },
30437
30438     
30439     lock: function() { this.locked = true; },
30440
30441     
30442     unlock: function() { this.locked = false; },
30443
30444     
30445     isLocked: function() { return this.locked; },
30446
30447     
30448     locationCache: {},
30449
30450     
30451     useCache: true,
30452
30453     
30454     clickPixelThresh: 3,
30455
30456     
30457     clickTimeThresh: 350,
30458
30459     
30460     dragThreshMet: false,
30461
30462     
30463     clickTimeout: null,
30464
30465     
30466     startX: 0,
30467
30468     
30469     startY: 0,
30470
30471     
30472     regDragDrop: function(oDD, sGroup) {
30473         if (!this.initialized) { this.init(); }
30474
30475         if (!this.ids[sGroup]) {
30476             this.ids[sGroup] = {};
30477         }
30478         this.ids[sGroup][oDD.id] = oDD;
30479     },
30480
30481     
30482     removeDDFromGroup: function(oDD, sGroup) {
30483         if (!this.ids[sGroup]) {
30484             this.ids[sGroup] = {};
30485         }
30486
30487         var obj = this.ids[sGroup];
30488         if (obj && obj[oDD.id]) {
30489             delete obj[oDD.id];
30490         }
30491     },
30492
30493     
30494     _remove: function(oDD) {
30495         for (var g in oDD.groups) {
30496             if (g && this.ids[g] && this.ids[g][oDD.id]) {
30497                 delete this.ids[g][oDD.id];
30498             }
30499         }
30500         delete this.handleIds[oDD.id];
30501     },
30502
30503     
30504     regHandle: function(sDDId, sHandleId) {
30505         if (!this.handleIds[sDDId]) {
30506             this.handleIds[sDDId] = {};
30507         }
30508         this.handleIds[sDDId][sHandleId] = sHandleId;
30509     },
30510
30511     
30512     isDragDrop: function(id) {
30513         return ( this.getDDById(id) ) ? true : false;
30514     },
30515
30516     
30517     getRelated: function(p_oDD, bTargetsOnly) {
30518         var oDDs = [];
30519         for (var i in p_oDD.groups) {
30520             for (var j in this.ids[i]) {
30521                 var dd = this.ids[i][j];
30522                 if (! this.isTypeOfDD(dd)) {
30523                     continue;
30524                 }
30525                 if (!bTargetsOnly || dd.isTarget) {
30526                     oDDs[oDDs.length] = dd;
30527                 }
30528             }
30529         }
30530
30531         return oDDs;
30532     },
30533
30534     
30535     isLegalTarget: function (oDD, oTargetDD) {
30536         var targets = this.getRelated(oDD, true);
30537         for (var i=0, len=targets.length;i<len;++i) {
30538             if (targets[i].id == oTargetDD.id) {
30539                 return true;
30540             }
30541         }
30542
30543         return false;
30544     },
30545
30546     
30547     isTypeOfDD: function (oDD) {
30548         return (oDD && oDD.__ygDragDrop);
30549     },
30550
30551     
30552     isHandle: function(sDDId, sHandleId) {
30553         return ( this.handleIds[sDDId] &&
30554                         this.handleIds[sDDId][sHandleId] );
30555     },
30556
30557     
30558     getDDById: function(id) {
30559         for (var i in this.ids) {
30560             if (this.ids[i][id]) {
30561                 return this.ids[i][id];
30562             }
30563         }
30564         return null;
30565     },
30566
30567     
30568     handleMouseDown: function(e, oDD) {
30569         if(Ext.tip.QuickTipManager){
30570             Ext.tip.QuickTipManager.ddDisable();
30571         }
30572         if(this.dragCurrent){
30573             
30574             
30575             this.handleMouseUp(e);
30576         }
30577
30578         this.currentTarget = e.getTarget();
30579         this.dragCurrent = oDD;
30580
30581         var el = oDD.getEl();
30582
30583         
30584         this.startX = e.getPageX();
30585         this.startY = e.getPageY();
30586
30587         this.deltaX = this.startX - el.offsetLeft;
30588         this.deltaY = this.startY - el.offsetTop;
30589
30590         this.dragThreshMet = false;
30591
30592         this.clickTimeout = setTimeout(
30593                 function() {
30594                     var DDM = Ext.dd.DragDropManager;
30595                     DDM.startDrag(DDM.startX, DDM.startY);
30596                 },
30597                 this.clickTimeThresh );
30598     },
30599
30600     
30601     startDrag: function(x, y) {
30602         clearTimeout(this.clickTimeout);
30603         if (this.dragCurrent) {
30604             this.dragCurrent.b4StartDrag(x, y);
30605             this.dragCurrent.startDrag(x, y);
30606         }
30607         this.dragThreshMet = true;
30608     },
30609
30610     
30611     handleMouseUp: function(e) {
30612
30613         if(Ext.tip && Ext.tip.QuickTipManager){
30614             Ext.tip.QuickTipManager.ddEnable();
30615         }
30616         if (! this.dragCurrent) {
30617             return;
30618         }
30619
30620         clearTimeout(this.clickTimeout);
30621
30622         if (this.dragThreshMet) {
30623             this.fireEvents(e, true);
30624         } else {
30625         }
30626
30627         this.stopDrag(e);
30628
30629         this.stopEvent(e);
30630     },
30631
30632     
30633     stopEvent: function(e){
30634         if(this.stopPropagation) {
30635             e.stopPropagation();
30636         }
30637
30638         if (this.preventDefault) {
30639             e.preventDefault();
30640         }
30641     },
30642
30643     
30644     stopDrag: function(e) {
30645         
30646         if (this.dragCurrent) {
30647             if (this.dragThreshMet) {
30648                 this.dragCurrent.b4EndDrag(e);
30649                 this.dragCurrent.endDrag(e);
30650             }
30651
30652             this.dragCurrent.onMouseUp(e);
30653         }
30654
30655         this.dragCurrent = null;
30656         this.dragOvers = {};
30657     },
30658
30659     
30660     handleMouseMove: function(e) {
30661         if (! this.dragCurrent) {
30662             return true;
30663         }
30664         
30665
30666         
30667         if (Ext.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
30668             this.stopEvent(e);
30669             return this.handleMouseUp(e);
30670         }
30671
30672         if (!this.dragThreshMet) {
30673             var diffX = Math.abs(this.startX - e.getPageX());
30674             var diffY = Math.abs(this.startY - e.getPageY());
30675             if (diffX > this.clickPixelThresh ||
30676                         diffY > this.clickPixelThresh) {
30677                 this.startDrag(this.startX, this.startY);
30678             }
30679         }
30680
30681         if (this.dragThreshMet) {
30682             this.dragCurrent.b4Drag(e);
30683             this.dragCurrent.onDrag(e);
30684             if(!this.dragCurrent.moveOnly){
30685                 this.fireEvents(e, false);
30686             }
30687         }
30688
30689         this.stopEvent(e);
30690
30691         return true;
30692     },
30693
30694     
30695     fireEvents: function(e, isDrop) {
30696         var dc = this.dragCurrent;
30697
30698         
30699         
30700         if (!dc || dc.isLocked()) {
30701             return;
30702         }
30703
30704         var pt = e.getPoint();
30705
30706         
30707         var oldOvers = [];
30708
30709         var outEvts   = [];
30710         var overEvts  = [];
30711         var dropEvts  = [];
30712         var enterEvts = [];
30713
30714         
30715         
30716         for (var i in this.dragOvers) {
30717
30718             var ddo = this.dragOvers[i];
30719
30720             if (! this.isTypeOfDD(ddo)) {
30721                 continue;
30722             }
30723
30724             if (! this.isOverTarget(pt, ddo, this.mode)) {
30725                 outEvts.push( ddo );
30726             }
30727
30728             oldOvers[i] = true;
30729             delete this.dragOvers[i];
30730         }
30731
30732         for (var sGroup in dc.groups) {
30733
30734             if ("string" != typeof sGroup) {
30735                 continue;
30736             }
30737
30738             for (i in this.ids[sGroup]) {
30739                 var oDD = this.ids[sGroup][i];
30740                 if (! this.isTypeOfDD(oDD)) {
30741                     continue;
30742                 }
30743
30744                 if (oDD.isTarget && !oDD.isLocked() && ((oDD != dc) || (dc.ignoreSelf === false))) {
30745                     if (this.isOverTarget(pt, oDD, this.mode)) {
30746                         
30747                         if (isDrop) {
30748                             dropEvts.push( oDD );
30749                         
30750                         } else {
30751
30752                             
30753                             if (!oldOvers[oDD.id]) {
30754                                 enterEvts.push( oDD );
30755                             
30756                             } else {
30757                                 overEvts.push( oDD );
30758                             }
30759
30760                             this.dragOvers[oDD.id] = oDD;
30761                         }
30762                     }
30763                 }
30764             }
30765         }
30766
30767         if (this.mode) {
30768             if (outEvts.length) {
30769                 dc.b4DragOut(e, outEvts);
30770                 dc.onDragOut(e, outEvts);
30771             }
30772
30773             if (enterEvts.length) {
30774                 dc.onDragEnter(e, enterEvts);
30775             }
30776
30777             if (overEvts.length) {
30778                 dc.b4DragOver(e, overEvts);
30779                 dc.onDragOver(e, overEvts);
30780             }
30781
30782             if (dropEvts.length) {
30783                 dc.b4DragDrop(e, dropEvts);
30784                 dc.onDragDrop(e, dropEvts);
30785             }
30786
30787         } else {
30788             
30789             var len = 0;
30790             for (i=0, len=outEvts.length; i<len; ++i) {
30791                 dc.b4DragOut(e, outEvts[i].id);
30792                 dc.onDragOut(e, outEvts[i].id);
30793             }
30794
30795             
30796             for (i=0,len=enterEvts.length; i<len; ++i) {
30797                 
30798                 dc.onDragEnter(e, enterEvts[i].id);
30799             }
30800
30801             
30802             for (i=0,len=overEvts.length; i<len; ++i) {
30803                 dc.b4DragOver(e, overEvts[i].id);
30804                 dc.onDragOver(e, overEvts[i].id);
30805             }
30806
30807             
30808             for (i=0, len=dropEvts.length; i<len; ++i) {
30809                 dc.b4DragDrop(e, dropEvts[i].id);
30810                 dc.onDragDrop(e, dropEvts[i].id);
30811             }
30812
30813         }
30814
30815         
30816         if (isDrop && !dropEvts.length) {
30817             dc.onInvalidDrop(e);
30818         }
30819
30820     },
30821
30822     
30823     getBestMatch: function(dds) {
30824         var winner = null;
30825         
30826         
30827            
30828         
30829         
30830
30831         var len = dds.length;
30832
30833         if (len == 1) {
30834             winner = dds[0];
30835         } else {
30836             
30837             for (var i=0; i<len; ++i) {
30838                 var dd = dds[i];
30839                 
30840                 
30841                 
30842                 if (dd.cursorIsOver) {
30843                     winner = dd;
30844                     break;
30845                 
30846                 } else {
30847                     if (!winner ||
30848                         winner.overlap.getArea() < dd.overlap.getArea()) {
30849                         winner = dd;
30850                     }
30851                 }
30852             }
30853         }
30854
30855         return winner;
30856     },
30857
30858     
30859     refreshCache: function(groups) {
30860         for (var sGroup in groups) {
30861             if ("string" != typeof sGroup) {
30862                 continue;
30863             }
30864             for (var i in this.ids[sGroup]) {
30865                 var oDD = this.ids[sGroup][i];
30866
30867                 if (this.isTypeOfDD(oDD)) {
30868                 
30869                     var loc = this.getLocation(oDD);
30870                     if (loc) {
30871                         this.locationCache[oDD.id] = loc;
30872                     } else {
30873                         delete this.locationCache[oDD.id];
30874                         
30875                         
30876                         
30877                     }
30878                 }
30879             }
30880         }
30881     },
30882
30883     
30884     verifyEl: function(el) {
30885         if (el) {
30886             var parent;
30887             if(Ext.isIE){
30888                 try{
30889                     parent = el.offsetParent;
30890                 }catch(e){}
30891             }else{
30892                 parent = el.offsetParent;
30893             }
30894             if (parent) {
30895                 return true;
30896             }
30897         }
30898
30899         return false;
30900     },
30901
30902     
30903     getLocation: function(oDD) {
30904         if (! this.isTypeOfDD(oDD)) {
30905             return null;
30906         }
30907
30908         
30909         
30910         if (oDD.getRegion) {
30911             return oDD.getRegion();
30912         }
30913
30914         var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
30915
30916         try {
30917             pos= Ext.Element.getXY(el);
30918         } catch (e) { }
30919
30920         if (!pos) {
30921             return null;
30922         }
30923
30924         x1 = pos[0];
30925         x2 = x1 + el.offsetWidth;
30926         y1 = pos[1];
30927         y2 = y1 + el.offsetHeight;
30928
30929         t = y1 - oDD.padding[0];
30930         r = x2 + oDD.padding[1];
30931         b = y2 + oDD.padding[2];
30932         l = x1 - oDD.padding[3];
30933
30934         return Ext.create('Ext.util.Region', t, r, b, l);
30935     },
30936
30937     
30938     isOverTarget: function(pt, oTarget, intersect) {
30939         
30940         var loc = this.locationCache[oTarget.id];
30941         if (!loc || !this.useCache) {
30942             loc = this.getLocation(oTarget);
30943             this.locationCache[oTarget.id] = loc;
30944
30945         }
30946
30947         if (!loc) {
30948             return false;
30949         }
30950
30951         oTarget.cursorIsOver = loc.contains( pt );
30952
30953         
30954         
30955         
30956         
30957         
30958         var dc = this.dragCurrent;
30959         if (!dc || !dc.getTargetCoord ||
30960                 (!intersect && !dc.constrainX && !dc.constrainY)) {
30961             return oTarget.cursorIsOver;
30962         }
30963
30964         oTarget.overlap = null;
30965
30966         
30967         
30968         
30969         
30970         var pos = dc.getTargetCoord(pt.x, pt.y);
30971
30972         var el = dc.getDragEl();
30973         var curRegion = Ext.create('Ext.util.Region', pos.y,
30974                                                pos.x + el.offsetWidth,
30975                                                pos.y + el.offsetHeight,
30976                                                pos.x );
30977
30978         var overlap = curRegion.intersect(loc);
30979
30980         if (overlap) {
30981             oTarget.overlap = overlap;
30982             return (intersect) ? true : oTarget.cursorIsOver;
30983         } else {
30984             return false;
30985         }
30986     },
30987
30988     
30989     _onUnload: function(e, me) {
30990         Ext.dd.DragDropManager.unregAll();
30991     },
30992
30993     
30994     unregAll: function() {
30995
30996         if (this.dragCurrent) {
30997             this.stopDrag();
30998             this.dragCurrent = null;
30999         }
31000
31001         this._execOnAll("unreg", []);
31002
31003         for (var i in this.elementCache) {
31004             delete this.elementCache[i];
31005         }
31006
31007         this.elementCache = {};
31008         this.ids = {};
31009     },
31010
31011     
31012     elementCache: {},
31013
31014     
31015     getElWrapper: function(id) {
31016         var oWrapper = this.elementCache[id];
31017         if (!oWrapper || !oWrapper.el) {
31018             oWrapper = this.elementCache[id] =
31019                 new this.ElementWrapper(Ext.getDom(id));
31020         }
31021         return oWrapper;
31022     },
31023
31024     
31025     getElement: function(id) {
31026         return Ext.getDom(id);
31027     },
31028
31029     
31030     getCss: function(id) {
31031         var el = Ext.getDom(id);
31032         return (el) ? el.style : null;
31033     },
31034
31035     
31036     ElementWrapper: function(el) {
31037         
31038         this.el = el || null;
31039         
31040         this.id = this.el && el.id;
31041         
31042         this.css = this.el && el.style;
31043     },
31044
31045     
31046     
31047
31048     
31049     getPosX: function(el) {
31050         return Ext.Element.getX(el);
31051     },
31052
31053     
31054     getPosY: function(el) {
31055         return Ext.Element.getY(el);
31056     },
31057
31058     
31059     swapNode: function(n1, n2) {
31060         if (n1.swapNode) {
31061             n1.swapNode(n2);
31062         } else {
31063             var p = n2.parentNode;
31064             var s = n2.nextSibling;
31065
31066             if (s == n1) {
31067                 p.insertBefore(n1, n2);
31068             } else if (n2 == n1.nextSibling) {
31069                 p.insertBefore(n2, n1);
31070             } else {
31071                 n1.parentNode.replaceChild(n2, n1);
31072                 p.insertBefore(n1, s);
31073             }
31074         }
31075     },
31076
31077     
31078     getScroll: function () {
31079         var doc   = window.document,
31080             docEl = doc.documentElement,
31081             body  = doc.body,
31082             top   = 0,
31083             left  = 0;
31084
31085         if (Ext.isGecko4) {
31086             top  = window.scrollYOffset;
31087             left = window.scrollXOffset;
31088         } else {
31089             if (docEl && (docEl.scrollTop || docEl.scrollLeft)) {
31090                 top  = docEl.scrollTop;
31091                 left = docEl.scrollLeft;
31092             } else if (body) {
31093                 top  = body.scrollTop;
31094                 left = body.scrollLeft;
31095             }
31096         }
31097         return {
31098             top: top,
31099             left: left
31100         };
31101     },
31102
31103     
31104     getStyle: function(el, styleProp) {
31105         return Ext.fly(el).getStyle(styleProp);
31106     },
31107
31108     
31109     getScrollTop: function () {
31110         return this.getScroll().top;
31111     },
31112
31113     
31114     getScrollLeft: function () {
31115         return this.getScroll().left;
31116     },
31117
31118     
31119     moveToEl: function (moveEl, targetEl) {
31120         var aCoord = Ext.Element.getXY(targetEl);
31121         Ext.Element.setXY(moveEl, aCoord);
31122     },
31123
31124     
31125     numericSort: function(a, b) {
31126         return (a - b);
31127     },
31128
31129     
31130     _timeoutCount: 0,
31131
31132     
31133     _addListeners: function() {
31134         if ( document ) {
31135             this._onLoad();
31136         } else {
31137             if (this._timeoutCount > 2000) {
31138             } else {
31139                 setTimeout(this._addListeners, 10);
31140                 if (document && document.body) {
31141                     this._timeoutCount += 1;
31142                 }
31143             }
31144         }
31145     },
31146
31147     
31148     handleWasClicked: function(node, id) {
31149         if (this.isHandle(id, node.id)) {
31150             return true;
31151         } else {
31152             
31153             var p = node.parentNode;
31154
31155             while (p) {
31156                 if (this.isHandle(id, p.id)) {
31157                     return true;
31158                 } else {
31159                     p = p.parentNode;
31160                 }
31161             }
31162         }
31163
31164         return false;
31165     }
31166 }, function() {
31167     this._addListeners();
31168 });
31169
31170
31171
31172 Ext.define('Ext.layout.container.Box', {
31173
31174     
31175
31176     alias: ['layout.box'],
31177     extend: 'Ext.layout.container.Container',
31178     alternateClassName: 'Ext.layout.BoxLayout',
31179
31180     requires: [
31181         'Ext.layout.container.boxOverflow.None',
31182         'Ext.layout.container.boxOverflow.Menu',
31183         'Ext.layout.container.boxOverflow.Scroller',
31184         'Ext.util.Format',
31185         'Ext.dd.DragDropManager'
31186     ],
31187
31188     
31189
31190     
31191
31192     
31193     defaultMargins: {
31194         top: 0,
31195         right: 0,
31196         bottom: 0,
31197         left: 0
31198     },
31199
31200     
31201     padding: '0',
31202     
31203     pack: 'start',
31204
31205     
31206     
31207
31208     type: 'box',
31209     scrollOffset: 0,
31210     itemCls: Ext.baseCSSPrefix + 'box-item',
31211     targetCls: Ext.baseCSSPrefix + 'box-layout-ct',
31212     innerCls: Ext.baseCSSPrefix + 'box-inner',
31213
31214     bindToOwnerCtContainer: true,
31215
31216     
31217     
31218     availableSpaceOffset: 0,
31219
31220     
31221     reserveOffset: true,
31222
31223     
31224     shrinkToFit: true,
31225
31226     
31227     clearInnerCtOnLayout: false,
31228
31229     flexSortFn: function (a, b) {
31230         var maxParallelPrefix = 'max' + this.parallelPrefixCap,
31231             infiniteValue = Infinity;
31232         a = a.component[maxParallelPrefix] || infiniteValue;
31233         b = b.component[maxParallelPrefix] || infiniteValue;
31234         
31235         if (!isFinite(a) && !isFinite(b)) {
31236             return false;
31237         }
31238         return a - b;
31239     },
31240
31241     
31242     minSizeSortFn: function(a, b) {
31243         return b.available - a.available;
31244     },
31245
31246     constructor: function(config) {
31247         var me = this;
31248
31249         me.callParent(arguments);
31250
31251         
31252         me.flexSortFn = Ext.Function.bind(me.flexSortFn, me);
31253
31254         me.initOverflowHandler();
31255     },
31256
31257     
31258     getChildBox: function(child) {
31259         child = child.el || this.owner.getComponent(child).el;
31260         var size = child.getBox(false, true);
31261         return {
31262             left: size.left,
31263             top: size.top,
31264             width: size.width,
31265             height: size.height
31266         };
31267     },
31268
31269     
31270     calculateChildBox: function(child) {
31271         var me = this,
31272             boxes = me.calculateChildBoxes(me.getVisibleItems(), me.getLayoutTargetSize()).boxes,
31273             ln = boxes.length,
31274             i = 0;
31275
31276         child = me.owner.getComponent(child);
31277         for (; i < ln; i++) {
31278             if (boxes[i].component === child) {
31279                 return boxes[i];
31280             }
31281         }
31282     },
31283
31284     
31285     calculateChildBoxes: function(visibleItems, targetSize) {
31286         var me = this,
31287             math = Math,
31288             mmax = math.max,
31289             infiniteValue = Infinity,
31290             undefinedValue,
31291
31292             parallelPrefix = me.parallelPrefix,
31293             parallelPrefixCap = me.parallelPrefixCap,
31294             perpendicularPrefix = me.perpendicularPrefix,
31295             perpendicularPrefixCap = me.perpendicularPrefixCap,
31296             parallelMinString = 'min' + parallelPrefixCap,
31297             perpendicularMinString = 'min' + perpendicularPrefixCap,
31298             perpendicularMaxString = 'max' + perpendicularPrefixCap,
31299
31300             parallelSize = targetSize[parallelPrefix] - me.scrollOffset,
31301             perpendicularSize = targetSize[perpendicularPrefix],
31302             padding = me.padding,
31303             parallelOffset = padding[me.parallelBefore],
31304             paddingParallel = parallelOffset + padding[me.parallelAfter],
31305             perpendicularOffset = padding[me.perpendicularLeftTop],
31306             paddingPerpendicular =  perpendicularOffset + padding[me.perpendicularRightBottom],
31307             availPerpendicularSize = mmax(0, perpendicularSize - paddingPerpendicular),
31308
31309             innerCtBorderWidth = me.innerCt.getBorderWidth(me.perpendicularLT + me.perpendicularRB),
31310
31311             isStart = me.pack == 'start',
31312             isCenter = me.pack == 'center',
31313             isEnd = me.pack == 'end',
31314
31315             constrain = Ext.Number.constrain,
31316             visibleCount = visibleItems.length,
31317             nonFlexSize = 0,
31318             totalFlex = 0,
31319             desiredSize = 0,
31320             minimumSize = 0,
31321             maxSize = 0,
31322             boxes = [],
31323             minSizes = [],
31324             calculatedWidth,
31325
31326             i, child, childParallel, childPerpendicular, childMargins, childSize, minParallel, tmpObj, shortfall,
31327             tooNarrow, availableSpace, minSize, item, length, itemIndex, box, oldSize, newSize, reduction, diff,
31328             flexedBoxes, remainingSpace, remainingFlex, flexedSize, parallelMargins, calcs, offset,
31329             perpendicularMargins, stretchSize;
31330
31331         
31332         for (i = 0; i < visibleCount; i++) {
31333             child = visibleItems[i];
31334             childPerpendicular = child[perpendicularPrefix];
31335             if (!child.flex || !(me.align == 'stretch' || me.align == 'stretchmax')) {
31336                 if (child.componentLayout.initialized !== true) {
31337                     me.layoutItem(child);
31338                 }
31339             }
31340
31341             childMargins = child.margins;
31342             parallelMargins = childMargins[me.parallelBefore] + childMargins[me.parallelAfter];
31343
31344             
31345             tmpObj = {
31346                 component: child,
31347                 margins: childMargins
31348             };
31349
31350             
31351             if (child.flex) {
31352                 totalFlex += child.flex;
31353                 childParallel = undefinedValue;
31354             }
31355             
31356             else {
31357                 if (!(child[parallelPrefix] && childPerpendicular)) {
31358                     childSize = child.getSize();
31359                 }
31360                 childParallel = child[parallelPrefix] || childSize[parallelPrefix];
31361                 childPerpendicular = childPerpendicular || childSize[perpendicularPrefix];
31362             }
31363
31364             nonFlexSize += parallelMargins + (childParallel || 0);
31365             desiredSize += parallelMargins + (child.flex ? child[parallelMinString] || 0 : childParallel);
31366             minimumSize += parallelMargins + (child[parallelMinString] || childParallel || 0);
31367
31368             
31369             if (typeof childPerpendicular != 'number') {
31370                 
31371                 
31372                 childPerpendicular = child['get' + perpendicularPrefixCap]();
31373             }
31374
31375             
31376             
31377             maxSize = mmax(maxSize, mmax(childPerpendicular, child[perpendicularMinString]||0) + childMargins[me.perpendicularLeftTop] + childMargins[me.perpendicularRightBottom]);
31378
31379             tmpObj[parallelPrefix] = childParallel || undefinedValue;
31380             tmpObj.dirtySize = child.componentLayout.lastComponentSize ? (tmpObj[parallelPrefix] !== child.componentLayout.lastComponentSize[parallelPrefix]) : false;
31381             tmpObj[perpendicularPrefix] = childPerpendicular || undefinedValue;
31382             boxes.push(tmpObj);
31383         }
31384
31385         
31386         if (!me.autoSize) {
31387             shortfall = desiredSize - parallelSize;
31388             tooNarrow = minimumSize > parallelSize;
31389         }
31390
31391         
31392         availableSpace = mmax(0, parallelSize - nonFlexSize - paddingParallel - (me.reserveOffset ? me.availableSpaceOffset : 0));
31393
31394         if (tooNarrow) {
31395             for (i = 0; i < visibleCount; i++) {
31396                 box = boxes[i];
31397                 minSize = visibleItems[i][parallelMinString] || visibleItems[i][parallelPrefix] || box[parallelPrefix];
31398                 box.dirtySize = box.dirtySize || box[parallelPrefix] != minSize;
31399                 box[parallelPrefix] = minSize;
31400             }
31401         }
31402         else {
31403             
31404             
31405             if (shortfall > 0) {
31406                 
31407                 for (i = 0; i < visibleCount; i++) {
31408                     item = visibleItems[i];
31409                     minSize = item[parallelMinString] || 0;
31410
31411                     
31412                     
31413                     if (item.flex) {
31414                         box = boxes[i];
31415                         box.dirtySize = box.dirtySize || box[parallelPrefix] != minSize;
31416                         box[parallelPrefix] = minSize;
31417                     } else if (me.shrinkToFit) {
31418                         minSizes.push({
31419                             minSize: minSize,
31420                             available: boxes[i][parallelPrefix] - minSize,
31421                             index: i
31422                         });
31423                     }
31424                 }
31425
31426                 
31427                 Ext.Array.sort(minSizes, me.minSizeSortFn);
31428
31429                 
31430                 for (i = 0, length = minSizes.length; i < length; i++) {
31431                     itemIndex = minSizes[i].index;
31432
31433                     if (itemIndex == undefinedValue) {
31434                         continue;
31435                     }
31436                     item = visibleItems[itemIndex];
31437                     minSize = minSizes[i].minSize;
31438
31439                     box = boxes[itemIndex];
31440                     oldSize = box[parallelPrefix];
31441                     newSize = mmax(minSize, oldSize - math.ceil(shortfall / (length - i)));
31442                     reduction = oldSize - newSize;
31443
31444                     box.dirtySize = box.dirtySize || box[parallelPrefix] != newSize;
31445                     box[parallelPrefix] = newSize;
31446                     shortfall -= reduction;
31447                 }
31448                 tooNarrow = (shortfall > 0);
31449             }
31450             else {
31451                 remainingSpace = availableSpace;
31452                 remainingFlex = totalFlex;
31453                 flexedBoxes = [];
31454
31455                 
31456                 for (i = 0; i < visibleCount; i++) {
31457                     child = visibleItems[i];
31458                     if (isStart && child.flex) {
31459                         flexedBoxes.push(boxes[Ext.Array.indexOf(visibleItems, child)]);
31460                     }
31461                 }
31462                 
31463                 
31464                 
31465                 Ext.Array.sort(flexedBoxes, me.flexSortFn);
31466
31467                 
31468                 for (i = 0; i < flexedBoxes.length; i++) {
31469                     calcs = flexedBoxes[i];
31470                     child = calcs.component;
31471                     childMargins = calcs.margins;
31472
31473                     flexedSize = math.ceil((child.flex / remainingFlex) * remainingSpace);
31474
31475                     
31476                     flexedSize = Math.max(child['min' + parallelPrefixCap] || 0, math.min(child['max' + parallelPrefixCap] || infiniteValue, flexedSize));
31477
31478                     
31479                     remainingSpace -= flexedSize;
31480                     remainingFlex -= child.flex;
31481
31482                     calcs.dirtySize = calcs.dirtySize || calcs[parallelPrefix] != flexedSize;
31483                     calcs[parallelPrefix] = flexedSize;
31484                 }
31485             }
31486         }
31487
31488         if (isCenter) {
31489             parallelOffset += availableSpace / 2;
31490         }
31491         else if (isEnd) {
31492             parallelOffset += availableSpace;
31493         }
31494
31495         
31496         
31497         
31498         
31499         if (me.owner.dock && (Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks) && !me.owner.width && me.direction == 'vertical') {
31500
31501             calculatedWidth = maxSize + me.owner.el.getPadding('lr') + me.owner.el.getBorderWidth('lr');
31502             if (me.owner.frameSize) {
31503                 calculatedWidth += me.owner.frameSize.left + me.owner.frameSize.right;
31504             }
31505             
31506             availPerpendicularSize = Math.min(availPerpendicularSize, targetSize.width = maxSize + padding.left + padding.right);
31507         }
31508
31509         
31510         for (i = 0; i < visibleCount; i++) {
31511             child = visibleItems[i];
31512             calcs = boxes[i];
31513
31514             childMargins = calcs.margins;
31515
31516             perpendicularMargins = childMargins[me.perpendicularLeftTop] + childMargins[me.perpendicularRightBottom];
31517
31518             
31519             parallelOffset += childMargins[me.parallelBefore];
31520
31521             calcs[me.parallelBefore] = parallelOffset;
31522             calcs[me.perpendicularLeftTop] = perpendicularOffset + childMargins[me.perpendicularLeftTop];
31523
31524             if (me.align == 'stretch') {
31525                 stretchSize = constrain(availPerpendicularSize - perpendicularMargins, child[perpendicularMinString] || 0, child[perpendicularMaxString] || infiniteValue);
31526                 calcs.dirtySize = calcs.dirtySize || calcs[perpendicularPrefix] != stretchSize;
31527                 calcs[perpendicularPrefix] = stretchSize;
31528             }
31529             else if (me.align == 'stretchmax') {
31530                 stretchSize = constrain(maxSize - perpendicularMargins, child[perpendicularMinString] || 0, child[perpendicularMaxString] || infiniteValue);
31531                 calcs.dirtySize = calcs.dirtySize || calcs[perpendicularPrefix] != stretchSize;
31532                 calcs[perpendicularPrefix] = stretchSize;
31533             }
31534             else if (me.align == me.alignCenteringString) {
31535                 
31536                 
31537                 
31538                 diff = mmax(availPerpendicularSize, maxSize) - innerCtBorderWidth - calcs[perpendicularPrefix];
31539                 if (diff > 0) {
31540                     calcs[me.perpendicularLeftTop] = perpendicularOffset + Math.round(diff / 2);
31541                 }
31542             }
31543
31544             
31545             parallelOffset += (calcs[parallelPrefix] || 0) + childMargins[me.parallelAfter];
31546         }
31547
31548         return {
31549             boxes: boxes,
31550             meta : {
31551                 calculatedWidth: calculatedWidth,
31552                 maxSize: maxSize,
31553                 nonFlexSize: nonFlexSize,
31554                 desiredSize: desiredSize,
31555                 minimumSize: minimumSize,
31556                 shortfall: shortfall,
31557                 tooNarrow: tooNarrow
31558             }
31559         };
31560     },
31561
31562     onRemove: function(comp){
31563         this.callParent(arguments);
31564         if (this.overflowHandler) {
31565             this.overflowHandler.onRemove(comp);
31566         }
31567     },
31568
31569     
31570     initOverflowHandler: function() {
31571         var handler = this.overflowHandler;
31572
31573         if (typeof handler == 'string') {
31574             handler = {
31575                 type: handler
31576             };
31577         }
31578
31579         var handlerType = 'None';
31580         if (handler && handler.type !== undefined) {
31581             handlerType = handler.type;
31582         }
31583
31584         var constructor = Ext.layout.container.boxOverflow[handlerType];
31585         if (constructor[this.type]) {
31586             constructor = constructor[this.type];
31587         }
31588
31589         this.overflowHandler = Ext.create('Ext.layout.container.boxOverflow.' + handlerType, this, handler);
31590     },
31591
31592     
31593     onLayout: function() {
31594         this.callParent();
31595         
31596         if (this.clearInnerCtOnLayout === true && this.adjustmentPass !== true) {
31597             this.innerCt.setSize(null, null);
31598         }
31599
31600         var me = this,
31601             targetSize = me.getLayoutTargetSize(),
31602             items = me.getVisibleItems(),
31603             calcs = me.calculateChildBoxes(items, targetSize),
31604             boxes = calcs.boxes,
31605             meta = calcs.meta,
31606             handler, method, results;
31607
31608         if (me.autoSize && calcs.meta.desiredSize) {
31609             targetSize[me.parallelPrefix] = calcs.meta.desiredSize;
31610         }
31611
31612         
31613         if (meta.shortfall > 0) {
31614             handler = me.overflowHandler;
31615             method = meta.tooNarrow ? 'handleOverflow': 'clearOverflow';
31616
31617             results = handler[method](calcs, targetSize);
31618
31619             if (results) {
31620                 if (results.targetSize) {
31621                     targetSize = results.targetSize;
31622                 }
31623
31624                 if (results.recalculate) {
31625                     items = me.getVisibleItems();
31626                     calcs = me.calculateChildBoxes(items, targetSize);
31627                     boxes = calcs.boxes;
31628                 }
31629             }
31630         } else {
31631             me.overflowHandler.clearOverflow();
31632         }
31633
31634         
31635         me.layoutTargetLastSize = targetSize;
31636
31637         
31638         me.childBoxCache = calcs;
31639
31640         me.updateInnerCtSize(targetSize, calcs);
31641         me.updateChildBoxes(boxes);
31642         me.handleTargetOverflow(targetSize);
31643     },
31644     
31645     animCallback: Ext.emptyFn,
31646
31647     
31648     updateChildBoxes: function(boxes) {
31649         var me = this,
31650             i = 0,
31651             length = boxes.length,
31652             animQueue = [],
31653             dd = Ext.dd.DDM.getDDById(me.innerCt.id), 
31654             oldBox, newBox, changed, comp, boxAnim, animCallback;
31655
31656         for (; i < length; i++) {
31657             newBox = boxes[i];
31658             comp = newBox.component;
31659
31660             
31661             
31662             if (dd && (dd.getDragEl() === comp.el.dom)) {
31663                 continue;
31664             }
31665
31666             changed = false;
31667
31668             oldBox = me.getChildBox(comp);
31669
31670             
31671             
31672             
31673             if (me.animate) {
31674                 
31675                 animCallback = me.animate.callback || me.animate;
31676                 boxAnim = {
31677                     layoutAnimation: true,  
31678                     target: comp,
31679                     from: {},
31680                     to: {},
31681                     listeners: {}
31682                 };
31683                 
31684                 
31685                 
31686                 
31687                 if (!isNaN(newBox.width) && (newBox.width != oldBox.width)) {
31688                     changed = true;
31689                     
31690                     boxAnim.to.width = newBox.width;
31691                 }
31692                 if (!isNaN(newBox.height) && (newBox.height != oldBox.height)) {
31693                     changed = true;
31694                     
31695                     boxAnim.to.height = newBox.height;
31696                 }
31697                 if (!isNaN(newBox.left) && (newBox.left != oldBox.left)) {
31698                     changed = true;
31699                     
31700                     boxAnim.to.left = newBox.left;
31701                 }
31702                 if (!isNaN(newBox.top) && (newBox.top != oldBox.top)) {
31703                     changed = true;
31704                     
31705                     boxAnim.to.top = newBox.top;
31706                 }
31707                 if (changed) {
31708                     animQueue.push(boxAnim);
31709                 }
31710             } else {
31711                 if (newBox.dirtySize) {
31712                     if (newBox.width !== oldBox.width || newBox.height !== oldBox.height) {
31713                         me.setItemSize(comp, newBox.width, newBox.height);
31714                     }
31715                 }
31716                 
31717                 if (isNaN(newBox.left) || isNaN(newBox.top)) {
31718                     continue;
31719                 }
31720                 comp.setPosition(newBox.left, newBox.top);
31721             }
31722         }
31723
31724         
31725         length = animQueue.length;
31726         if (length) {
31727
31728             
31729             
31730             var afterAnimate = function(anim) {
31731                 
31732                 length -= 1;
31733                 if (!length) {
31734                     me.animCallback(anim);
31735                     me.layoutBusy = false;
31736                     if (Ext.isFunction(animCallback)) {
31737                         animCallback();
31738                     }
31739                 }
31740             };
31741
31742             var beforeAnimate = function() {
31743                 me.layoutBusy = true;
31744             };
31745
31746             
31747             for (i = 0, length = animQueue.length; i < length; i++) {
31748                 boxAnim = animQueue[i];
31749
31750                 
31751                 boxAnim.listeners.afteranimate = afterAnimate;
31752
31753                 
31754                 if (!i) {
31755                     boxAnim.listeners.beforeanimate = beforeAnimate;
31756                 }
31757                 if (me.animate.duration) {
31758                     boxAnim.duration = me.animate.duration;
31759                 }
31760                 comp = boxAnim.target;
31761                 delete boxAnim.target;
31762                 
31763                 comp.stopAnimation();
31764                 comp.animate(boxAnim);
31765             }
31766         }
31767     },
31768
31769     
31770     updateInnerCtSize: function(tSize, calcs) {
31771         var me = this,
31772             mmax = Math.max,
31773             align = me.align,
31774             padding = me.padding,
31775             width = tSize.width,
31776             height = tSize.height,
31777             meta = calcs.meta,
31778             innerCtWidth,
31779             innerCtHeight;
31780
31781         if (me.direction == 'horizontal') {
31782             innerCtWidth = width;
31783             innerCtHeight = meta.maxSize + padding.top + padding.bottom + me.innerCt.getBorderWidth('tb');
31784
31785             if (align == 'stretch') {
31786                 innerCtHeight = height;
31787             }
31788             else if (align == 'middle') {
31789                 innerCtHeight = mmax(height, innerCtHeight);
31790             }
31791         } else {
31792             innerCtHeight = height;
31793             innerCtWidth = meta.maxSize + padding.left + padding.right + me.innerCt.getBorderWidth('lr');
31794
31795             if (align == 'stretch') {
31796                 innerCtWidth = width;
31797             }
31798             else if (align == 'center') {
31799                 innerCtWidth = mmax(width, innerCtWidth);
31800             }
31801         }
31802         me.getRenderTarget().setSize(innerCtWidth || undefined, innerCtHeight || undefined);
31803
31804         
31805         
31806         if (meta.calculatedWidth && me.owner.el.getWidth() > meta.calculatedWidth) {
31807             me.owner.el.setWidth(meta.calculatedWidth);
31808         }
31809
31810         if (me.innerCt.dom.scrollTop) {
31811             me.innerCt.dom.scrollTop = 0;
31812         }
31813     },
31814
31815     
31816     handleTargetOverflow: function(previousTargetSize) {
31817         var target = this.getTarget(),
31818             overflow = target.getStyle('overflow'),
31819             newTargetSize;
31820
31821         if (overflow && overflow != 'hidden' && !this.adjustmentPass) {
31822             newTargetSize = this.getLayoutTargetSize();
31823             if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height) {
31824                 this.adjustmentPass = true;
31825                 this.onLayout();
31826                 return true;
31827             }
31828         }
31829
31830         delete this.adjustmentPass;
31831     },
31832
31833     
31834     isValidParent : function(item, target, position) {
31835         
31836         
31837         var itemEl = item.el ? item.el.dom : Ext.getDom(item);
31838         return (itemEl && this.innerCt && itemEl.parentNode === this.innerCt.dom) || false;
31839     },
31840
31841     
31842     
31843     getRenderTarget: function() {
31844         if (!this.innerCt) {
31845             
31846             this.innerCt = this.getTarget().createChild({
31847                 cls: this.innerCls,
31848                 role: 'presentation'
31849             });
31850             this.padding = Ext.util.Format.parseBox(this.padding);
31851         }
31852         return this.innerCt;
31853     },
31854
31855     
31856     renderItem: function(item, target) {
31857         this.callParent(arguments);
31858         var me = this,
31859             itemEl = item.getEl(),
31860             style = itemEl.dom.style,
31861             margins = item.margins || item.margin;
31862
31863         
31864         if (margins) {
31865             if (Ext.isString(margins) || Ext.isNumber(margins)) {
31866                 margins = Ext.util.Format.parseBox(margins);
31867             } else {
31868                 Ext.applyIf(margins, {top: 0, right: 0, bottom: 0, left: 0});
31869             }
31870         } else {
31871             margins = Ext.apply({}, me.defaultMargins);
31872         }
31873
31874         
31875         margins.top    += itemEl.getMargin('t');
31876         margins.right  += itemEl.getMargin('r');
31877         margins.bottom += itemEl.getMargin('b');
31878         margins.left   += itemEl.getMargin('l');
31879         margins.height  = margins.top  + margins.bottom;
31880         margins.width   = margins.left + margins.right;
31881         style.marginTop = style.marginRight = style.marginBottom = style.marginLeft = '0';
31882
31883         
31884         item.margins = margins;
31885     },
31886
31887     
31888     destroy: function() {
31889         Ext.destroy(this.innerCt, this.overflowHandler);
31890         this.callParent(arguments);
31891     }
31892 });
31893
31894 Ext.define('Ext.layout.container.HBox', {
31895
31896     
31897
31898     alias: ['layout.hbox'],
31899     extend: 'Ext.layout.container.Box',
31900     alternateClassName: 'Ext.layout.HBoxLayout',
31901
31902     
31903
31904     
31905     align: 'top', 
31906
31907     //@private
31908
31909     alignCenteringString: 'middle',
31910
31911     type : 'hbox',
31912
31913     direction: 'horizontal',
31914
31915     
31916     parallelSizeIndex: 0,
31917     perpendicularSizeIndex: 1,
31918
31919     parallelPrefix: 'width',
31920     parallelPrefixCap: 'Width',
31921     parallelLT: 'l',
31922     parallelRB: 'r',
31923     parallelBefore: 'left',
31924     parallelBeforeCap: 'Left',
31925     parallelAfter: 'right',
31926     parallelPosition: 'x',
31927
31928     perpendicularPrefix: 'height',
31929     perpendicularPrefixCap: 'Height',
31930     perpendicularLT: 't',
31931     perpendicularRB: 'b',
31932     perpendicularLeftTop: 'top',
31933     perpendicularRightBottom: 'bottom',
31934     perpendicularPosition: 'y',
31935     configureItem: function(item) {
31936         if (item.flex) {
31937             item.layoutManagedWidth = 1;
31938         } else {
31939             item.layoutManagedWidth = 2;
31940         }
31941
31942         if (this.align === 'stretch' || this.align === 'stretchmax') {
31943             item.layoutManagedHeight = 1;
31944         } else {
31945             item.layoutManagedHeight = 2;
31946         }
31947         this.callParent(arguments);
31948     }
31949 });
31950
31951 Ext.define('Ext.layout.container.VBox', {
31952
31953     
31954
31955     alias: ['layout.vbox'],
31956     extend: 'Ext.layout.container.Box',
31957     alternateClassName: 'Ext.layout.VBoxLayout',
31958
31959     
31960
31961     
31962     align : 'left', 
31963
31964     //@private
31965
31966     alignCenteringString: 'center',
31967
31968     type: 'vbox',
31969
31970     direction: 'vertical',
31971
31972     
31973     parallelSizeIndex: 1,
31974     perpendicularSizeIndex: 0,
31975
31976     parallelPrefix: 'height',
31977     parallelPrefixCap: 'Height',
31978     parallelLT: 't',
31979     parallelRB: 'b',
31980     parallelBefore: 'top',
31981     parallelBeforeCap: 'Top',
31982     parallelAfter: 'bottom',
31983     parallelPosition: 'y',
31984
31985     perpendicularPrefix: 'width',
31986     perpendicularPrefixCap: 'Width',
31987     perpendicularLT: 'l',
31988     perpendicularRB: 'r',
31989     perpendicularLeftTop: 'left',
31990     perpendicularRightBottom: 'right',
31991     perpendicularPosition: 'x',
31992     configureItem: function(item) {
31993         if (item.flex) {
31994             item.layoutManagedHeight = 1;
31995         } else {
31996             item.layoutManagedHeight = 2;
31997         }
31998
31999         if (this.align === 'stretch' || this.align === 'stretchmax') {
32000             item.layoutManagedWidth = 1;
32001         } else {
32002             item.layoutManagedWidth = 2;
32003         }
32004         this.callParent(arguments);
32005     }
32006 });
32007
32008 Ext.define('Ext.FocusManager', {
32009     singleton: true,
32010     alternateClassName: 'Ext.FocusMgr',
32011
32012     mixins: {
32013         observable: 'Ext.util.Observable'
32014     },
32015
32016     requires: [
32017         'Ext.ComponentManager',
32018         'Ext.ComponentQuery',
32019         'Ext.util.HashMap',
32020         'Ext.util.KeyNav'
32021     ],
32022
32023     
32024     enabled: false,
32025
32026     
32027
32028     focusElementCls: Ext.baseCSSPrefix + 'focus-element',
32029
32030     focusFrameCls: Ext.baseCSSPrefix + 'focus-frame',
32031
32032     
32033     whitelist: [
32034         'textfield'
32035     ],
32036
32037     tabIndexWhitelist: [
32038         'a',
32039         'button',
32040         'embed',
32041         'frame',
32042         'iframe',
32043         'img',
32044         'input',
32045         'object',
32046         'select',
32047         'textarea'
32048     ],
32049
32050     constructor: function() {
32051         var me = this,
32052             CQ = Ext.ComponentQuery;
32053
32054         me.addEvents(
32055             
32056             'beforecomponentfocus',
32057
32058             
32059             'componentfocus',
32060
32061             
32062             'disable',
32063
32064             
32065             'enable'
32066         );
32067
32068         
32069         
32070         me.keyNav = Ext.create('Ext.util.KeyNav', Ext.getDoc(), {
32071             disabled: true,
32072             scope: me,
32073
32074             backspace: me.focusLast,
32075             enter: me.navigateIn,
32076             esc: me.navigateOut,
32077             tab: me.navigateSiblings
32078
32079             
32080             
32081             
32082             
32083             
32084             
32085         });
32086
32087         me.focusData = {};
32088         me.subscribers = Ext.create('Ext.util.HashMap');
32089         me.focusChain = {};
32090
32091         
32092         Ext.apply(CQ.pseudos, {
32093             focusable: function(cmps) {
32094                 var len = cmps.length,
32095                     results = [],
32096                     i = 0,
32097                     c,
32098
32099                     isFocusable = function(x) {
32100                         return x && x.focusable !== false && CQ.is(x, '[rendered]:not([destroying]):not([isDestroyed]):not([disabled]){isVisible(true)}{el && c.el.dom && c.el.isVisible()}');
32101                     };
32102
32103                 for (; i < len; i++) {
32104                     c = cmps[i];
32105                     if (isFocusable(c)) {
32106                         results.push(c);
32107                     }
32108                 }
32109
32110                 return results;
32111             },
32112
32113             nextFocus: function(cmps, idx, step) {
32114                 step = step || 1;
32115                 idx = parseInt(idx, 10);
32116
32117                 var len = cmps.length,
32118                     i = idx + step,
32119                     c;
32120
32121                 for (; i != idx; i += step) {
32122                     if (i >= len) {
32123                         i = 0;
32124                     } else if (i < 0) {
32125                         i = len - 1;
32126                     }
32127
32128                     c = cmps[i];
32129                     if (CQ.is(c, ':focusable')) {
32130                         return [c];
32131                     } else if (c.placeholder && CQ.is(c.placeholder, ':focusable')) {
32132                         return [c.placeholder];
32133                     }
32134                 }
32135
32136                 return [];
32137             },
32138
32139             prevFocus: function(cmps, idx) {
32140                 return this.nextFocus(cmps, idx, -1);
32141             },
32142
32143             root: function(cmps) {
32144                 var len = cmps.length,
32145                     results = [],
32146                     i = 0,
32147                     c;
32148
32149                 for (; i < len; i++) {
32150                     c = cmps[i];
32151                     if (!c.ownerCt) {
32152                         results.push(c);
32153                     }
32154                 }
32155
32156                 return results;
32157             }
32158         });
32159     },
32160
32161     
32162     addXTypeToWhitelist: function(xtype) {
32163         var me = this;
32164
32165         if (Ext.isArray(xtype)) {
32166             Ext.Array.forEach(xtype, me.addXTypeToWhitelist, me);
32167             return;
32168         }
32169
32170         if (!Ext.Array.contains(me.whitelist, xtype)) {
32171             me.whitelist.push(xtype);
32172         }
32173     },
32174
32175     clearComponent: function(cmp) {
32176         clearTimeout(this.cmpFocusDelay);
32177         if (!cmp.isDestroyed) {
32178             cmp.blur();
32179         }
32180     },
32181
32182     
32183     disable: function() {
32184         var me = this;
32185
32186         if (!me.enabled) {
32187             return;
32188         }
32189
32190         delete me.options;
32191         me.enabled = false;
32192
32193         Ext.ComponentManager.all.un('add', me.onComponentCreated, me);
32194
32195         me.removeDOM();
32196
32197         
32198         me.keyNav.disable();
32199
32200         
32201         me.setFocusAll(false);
32202
32203         me.fireEvent('disable', me);
32204     },
32205
32206     
32207     enable: function(options) {
32208         var me = this;
32209
32210         if (options === true) {
32211             options = { focusFrame: true };
32212         }
32213         me.options = options = options || {};
32214
32215         if (me.enabled) {
32216             return;
32217         }
32218
32219         
32220         Ext.ComponentManager.all.on('add', me.onComponentCreated, me);
32221
32222         me.initDOM(options);
32223
32224         
32225         me.keyNav.enable();
32226
32227         
32228         me.setFocusAll(true, options);
32229
32230         
32231         me.focusEl.focus();
32232         delete me.focusedCmp;
32233
32234         me.enabled = true;
32235         me.fireEvent('enable', me);
32236     },
32237
32238     focusLast: function(e) {
32239         var me = this;
32240
32241         if (me.isWhitelisted(me.focusedCmp)) {
32242             return true;
32243         }
32244
32245         
32246         if (me.previousFocusedCmp) {
32247             me.previousFocusedCmp.focus();
32248         }
32249     },
32250
32251     getRootComponents: function() {
32252         var me = this,
32253             CQ = Ext.ComponentQuery,
32254             inline = CQ.query(':focusable:root:not([floating])'),
32255             floating = CQ.query(':focusable:root[floating]');
32256
32257         
32258         
32259         floating.sort(function(a, b) {
32260             return a.el.getZIndex() > b.el.getZIndex();
32261         });
32262
32263         return floating.concat(inline);
32264     },
32265
32266     initDOM: function(options) {
32267         var me = this,
32268             sp = '&#160',
32269             cls = me.focusFrameCls;
32270
32271         if (!Ext.isReady) {
32272             Ext.onReady(me.initDOM, me);
32273             return;
32274         }
32275
32276         
32277         if (!me.focusEl) {
32278             me.focusEl = Ext.getBody().createChild({
32279                 tabIndex: '-1',
32280                 cls: me.focusElementCls,
32281                 html: sp
32282             });
32283         }
32284
32285         
32286         if (!me.focusFrame && options.focusFrame) {
32287             me.focusFrame = Ext.getBody().createChild({
32288                 cls: cls,
32289                 children: [
32290                     { cls: cls + '-top' },
32291                     { cls: cls + '-bottom' },
32292                     { cls: cls + '-left' },
32293                     { cls: cls + '-right' }
32294                 ],
32295                 style: 'top: -100px; left: -100px;'
32296             });
32297             me.focusFrame.setVisibilityMode(Ext.Element.DISPLAY);
32298             me.focusFrameWidth = 2;
32299             me.focusFrame.hide().setLeftTop(0, 0);
32300         }
32301     },
32302
32303     isWhitelisted: function(cmp) {
32304         return cmp && Ext.Array.some(this.whitelist, function(x) {
32305             return cmp.isXType(x);
32306         });
32307     },
32308
32309     navigateIn: function(e) {
32310         var me = this,
32311             focusedCmp = me.focusedCmp,
32312             rootCmps,
32313             firstChild;
32314
32315         if (!focusedCmp) {
32316             
32317             rootCmps = me.getRootComponents();
32318             if (rootCmps.length) {
32319                 rootCmps[0].focus();
32320             }
32321         } else {
32322             
32323             
32324             firstChild = Ext.ComponentQuery.query('>:focusable', focusedCmp)[0];
32325             if (firstChild) {
32326                 firstChild.focus();
32327             } else {
32328                 
32329                 if (Ext.isFunction(focusedCmp.onClick)) {
32330                     e.button = 0;
32331                     focusedCmp.onClick(e);
32332                     focusedCmp.focus();
32333                 }
32334             }
32335         }
32336     },
32337
32338     navigateOut: function(e) {
32339         var me = this,
32340             parent;
32341
32342         if (!me.focusedCmp || !(parent = me.focusedCmp.up(':focusable'))) {
32343             me.focusEl.focus();
32344         } else {
32345             parent.focus();
32346         }
32347
32348         
32349         
32350         
32351         return true;
32352     },
32353
32354     navigateSiblings: function(e, source, parent) {
32355         var me = this,
32356             src = source || me,
32357             key = e.getKey(),
32358             EO = Ext.EventObject,
32359             goBack = e.shiftKey || key == EO.LEFT || key == EO.UP,
32360             checkWhitelist = key == EO.LEFT || key == EO.RIGHT || key == EO.UP || key == EO.DOWN,
32361             nextSelector = goBack ? 'prev' : 'next',
32362             idx, next, focusedCmp;
32363
32364         focusedCmp = (src.focusedCmp && src.focusedCmp.comp) || src.focusedCmp;
32365         if (!focusedCmp && !parent) {
32366             return;
32367         }
32368
32369         if (checkWhitelist && me.isWhitelisted(focusedCmp)) {
32370             return true;
32371         }
32372
32373         parent = parent || focusedCmp.up();
32374         if (parent) {
32375             idx = focusedCmp ? Ext.Array.indexOf(parent.getRefItems(), focusedCmp) : -1;
32376             next = Ext.ComponentQuery.query('>:' + nextSelector + 'Focus(' + idx + ')', parent)[0];
32377             if (next && focusedCmp !== next) {
32378                 next.focus();
32379                 return next;
32380             }
32381         }
32382     },
32383
32384     onComponentBlur: function(cmp, e) {
32385         var me = this;
32386
32387         if (me.focusedCmp === cmp) {
32388             me.previousFocusedCmp = cmp;
32389             delete me.focusedCmp;
32390         }
32391
32392         if (me.focusFrame) {
32393             me.focusFrame.hide();
32394         }
32395     },
32396
32397     onComponentCreated: function(hash, id, cmp) {
32398         this.setFocus(cmp, true, this.options);
32399     },
32400
32401     onComponentDestroy: function(cmp) {
32402         this.setFocus(cmp, false);
32403     },
32404
32405     onComponentFocus: function(cmp, e) {
32406         var me = this,
32407             chain = me.focusChain;
32408
32409         if (!Ext.ComponentQuery.is(cmp, ':focusable')) {
32410             me.clearComponent(cmp);
32411
32412             
32413             
32414             
32415             
32416             if (chain[cmp.id]) {
32417                 return;
32418             }
32419
32420             
32421             var parent = cmp.up();
32422             if (parent) {
32423                 
32424                 
32425                 
32426                 chain[cmp.id] = true;
32427                 parent.focus();
32428             }
32429
32430             return;
32431         }
32432
32433         
32434         me.focusChain = {};
32435
32436         
32437         
32438         clearTimeout(me.cmpFocusDelay);
32439         if (arguments.length !== 2) {
32440             me.cmpFocusDelay = Ext.defer(me.onComponentFocus, 90, me, [cmp, e]);
32441             return;
32442         }
32443
32444         if (me.fireEvent('beforecomponentfocus', me, cmp, me.previousFocusedCmp) === false) {
32445             me.clearComponent(cmp);
32446             return;
32447         }
32448
32449         me.focusedCmp = cmp;
32450
32451         
32452         if (me.shouldShowFocusFrame(cmp)) {
32453             var cls = '.' + me.focusFrameCls + '-',
32454                 ff = me.focusFrame,
32455                 fw = me.focusFrameWidth,
32456                 box = cmp.el.getPageBox(),
32457
32458             
32459             
32460             
32461                 bt = box.top,
32462                 bl = box.left,
32463                 bw = box.width,
32464                 bh = box.height,
32465                 ft = ff.child(cls + 'top'),
32466                 fb = ff.child(cls + 'bottom'),
32467                 fl = ff.child(cls + 'left'),
32468                 fr = ff.child(cls + 'right');
32469
32470             ft.setWidth(bw).setLeftTop(bl, bt);
32471             fb.setWidth(bw).setLeftTop(bl, bt + bh - fw);
32472             fl.setHeight(bh - fw - fw).setLeftTop(bl, bt + fw);
32473             fr.setHeight(bh - fw - fw).setLeftTop(bl + bw - fw, bt + fw);
32474
32475             ff.show();
32476         }
32477
32478         me.fireEvent('componentfocus', me, cmp, me.previousFocusedCmp);
32479     },
32480
32481     onComponentHide: function(cmp) {
32482         var me = this,
32483             CQ = Ext.ComponentQuery,
32484             cmpHadFocus = false,
32485             focusedCmp,
32486             parent;
32487
32488         if (me.focusedCmp) {
32489             focusedCmp = CQ.query('[id=' + me.focusedCmp.id + ']', cmp)[0];
32490             cmpHadFocus = me.focusedCmp.id === cmp.id || focusedCmp;
32491
32492             if (focusedCmp) {
32493                 me.clearComponent(focusedCmp);
32494             }
32495         }
32496
32497         me.clearComponent(cmp);
32498
32499         if (cmpHadFocus) {
32500             parent = CQ.query('^:focusable', cmp)[0];
32501             if (parent) {
32502                 parent.focus();
32503             }
32504         }
32505     },
32506
32507     removeDOM: function() {
32508         var me = this;
32509
32510         
32511         
32512         if (me.enabled || me.subscribers.length) {
32513             return;
32514         }
32515
32516         Ext.destroy(
32517             me.focusEl,
32518             me.focusFrame
32519         );
32520         delete me.focusEl;
32521         delete me.focusFrame;
32522         delete me.focusFrameWidth;
32523     },
32524
32525     
32526     removeXTypeFromWhitelist: function(xtype) {
32527         var me = this;
32528
32529         if (Ext.isArray(xtype)) {
32530             Ext.Array.forEach(xtype, me.removeXTypeFromWhitelist, me);
32531             return;
32532         }
32533
32534         Ext.Array.remove(me.whitelist, xtype);
32535     },
32536
32537     setFocus: function(cmp, focusable, options) {
32538         var me = this,
32539             el, dom, data,
32540
32541             needsTabIndex = function(n) {
32542                 return !Ext.Array.contains(me.tabIndexWhitelist, n.tagName.toLowerCase())
32543                     && n.tabIndex <= 0;
32544             };
32545
32546         options = options || {};
32547
32548         
32549         if (!cmp.rendered) {
32550             cmp.on('afterrender', Ext.pass(me.setFocus, arguments, me), me, { single: true });
32551             return;
32552         }
32553
32554         el = cmp.getFocusEl();
32555         dom = el.dom;
32556
32557         
32558         if ((focusable && !me.focusData[cmp.id]) || (!focusable && me.focusData[cmp.id])) {
32559             if (focusable) {
32560                 data = {
32561                     focusFrame: options.focusFrame
32562                 };
32563
32564                 
32565                 
32566                 
32567                 
32568                 if (needsTabIndex(dom)) {
32569                     data.tabIndex = dom.tabIndex;
32570                     dom.tabIndex = -1;
32571                 }
32572
32573                 el.on({
32574                     focus: data.focusFn = Ext.bind(me.onComponentFocus, me, [cmp], 0),
32575                     blur: data.blurFn = Ext.bind(me.onComponentBlur, me, [cmp], 0),
32576                     scope: me
32577                 });
32578                 cmp.on({
32579                     hide: me.onComponentHide,
32580                     close: me.onComponentHide,
32581                     beforedestroy: me.onComponentDestroy,
32582                     scope: me
32583                 });
32584
32585                 me.focusData[cmp.id] = data;
32586             } else {
32587                 data = me.focusData[cmp.id];
32588                 if ('tabIndex' in data) {
32589                     dom.tabIndex = data.tabIndex;
32590                 }
32591                 el.un('focus', data.focusFn, me);
32592                 el.un('blur', data.blurFn, me);
32593                 cmp.un('hide', me.onComponentHide, me);
32594                 cmp.un('close', me.onComponentHide, me);
32595                 cmp.un('beforedestroy', me.onComponentDestroy, me);
32596
32597                 delete me.focusData[cmp.id];
32598             }
32599         }
32600     },
32601
32602     setFocusAll: function(focusable, options) {
32603         var me = this,
32604             cmps = Ext.ComponentManager.all.getArray(),
32605             len = cmps.length,
32606             cmp,
32607             i = 0;
32608
32609         for (; i < len; i++) {
32610             me.setFocus(cmps[i], focusable, options);
32611         }
32612     },
32613
32614     setupSubscriberKeys: function(container, keys) {
32615         var me = this,
32616             el = container.getFocusEl(),
32617             scope = keys.scope,
32618             handlers = {
32619                 backspace: me.focusLast,
32620                 enter: me.navigateIn,
32621                 esc: me.navigateOut,
32622                 scope: me
32623             },
32624
32625             navSiblings = function(e) {
32626                 if (me.focusedCmp === container) {
32627                     
32628                     
32629                     
32630                     return me.navigateSiblings(e, me, container);
32631                 } else {
32632                     return me.navigateSiblings(e);
32633                 }
32634             };
32635
32636         Ext.iterate(keys, function(key, cb) {
32637             handlers[key] = function(e) {
32638                 var ret = navSiblings(e);
32639
32640                 if (Ext.isFunction(cb) && cb.call(scope || container, e, ret) === true) {
32641                     return true;
32642                 }
32643
32644                 return ret;
32645             };
32646         }, me);
32647
32648         return Ext.create('Ext.util.KeyNav', el, handlers);
32649     },
32650
32651     shouldShowFocusFrame: function(cmp) {
32652         var me = this,
32653             opts = me.options || {};
32654
32655         if (!me.focusFrame || !cmp) {
32656             return false;
32657         }
32658
32659         
32660         if (opts.focusFrame) {
32661             return true;
32662         }
32663
32664         if (me.focusData[cmp.id].focusFrame) {
32665             return true;
32666         }
32667
32668         return false;
32669     },
32670
32671     
32672     subscribe: function(container, options) {
32673         var me = this,
32674             EA = Ext.Array,
32675             data = {},
32676             subs = me.subscribers,
32677
32678             
32679             
32680             
32681             safeSetFocus = function(cmp) {
32682                 if (cmp.isContainer && !subs.containsKey(cmp.id)) {
32683                     EA.forEach(cmp.query('>'), safeSetFocus);
32684                     me.setFocus(cmp, true, options);
32685                     cmp.on('add', data.onAdd, me);
32686                 } else if (!cmp.isContainer) {
32687                     me.setFocus(cmp, true, options);
32688                 }
32689             };
32690
32691         
32692         if (!container || !container.isContainer) {
32693             return;
32694         }
32695
32696         if (!container.rendered) {
32697             container.on('afterrender', Ext.pass(me.subscribe, arguments, me), me, { single: true });
32698             return;
32699         }
32700
32701         
32702         me.initDOM(options);
32703
32704         
32705         data.keyNav = me.setupSubscriberKeys(container, options.keys);
32706
32707         
32708         
32709         
32710         
32711         data.onAdd = function(ct, cmp, idx) {
32712             safeSetFocus(cmp);
32713         };
32714         container.on('beforedestroy', me.unsubscribe, me);
32715
32716         
32717         safeSetFocus(container);
32718
32719         
32720         subs.add(container.id, data);
32721     },
32722
32723     
32724     unsubscribe: function(container) {
32725         var me = this,
32726             EA = Ext.Array,
32727             subs = me.subscribers,
32728             data,
32729
32730             
32731             
32732             
32733             safeSetFocus = function(cmp) {
32734                 if (cmp.isContainer && !subs.containsKey(cmp.id)) {
32735                     EA.forEach(cmp.query('>'), safeSetFocus);
32736                     me.setFocus(cmp, false);
32737                     cmp.un('add', data.onAdd, me);
32738                 } else if (!cmp.isContainer) {
32739                     me.setFocus(cmp, false);
32740                 }
32741             };
32742
32743         if (!container || !subs.containsKey(container.id)) {
32744             return;
32745         }
32746
32747         data = subs.get(container.id);
32748         data.keyNav.destroy();
32749         container.un('beforedestroy', me.unsubscribe, me);
32750         subs.removeAtKey(container.id);
32751         safeSetFocus(container);
32752         me.removeDOM();
32753     }
32754 });
32755
32756 Ext.define('Ext.toolbar.Toolbar', {
32757     extend: 'Ext.container.Container',
32758     requires: [
32759         'Ext.toolbar.Fill',
32760         'Ext.layout.container.HBox',
32761         'Ext.layout.container.VBox',
32762         'Ext.FocusManager'
32763     ],
32764     uses: [
32765         'Ext.toolbar.Separator'
32766     ],
32767     alias: 'widget.toolbar',
32768     alternateClassName: 'Ext.Toolbar',
32769
32770     isToolbar: true,
32771     baseCls  : Ext.baseCSSPrefix + 'toolbar',
32772     ariaRole : 'toolbar',
32773
32774     defaultType: 'button',
32775
32776     
32777     vertical: false,
32778
32779     
32780
32781     
32782     enableOverflow: false,
32783
32784     
32785     menuTriggerCls: Ext.baseCSSPrefix + 'toolbar-more-icon',
32786     
32787     
32788     trackMenus: true,
32789
32790     itemCls: Ext.baseCSSPrefix + 'toolbar-item',
32791
32792     initComponent: function() {
32793         var me = this,
32794             keys;
32795
32796         
32797         if (!me.layout && me.enableOverflow) {
32798             me.layout = { overflowHandler: 'Menu' };
32799         }
32800
32801         if (me.dock === 'right' || me.dock === 'left') {
32802             me.vertical = true;
32803         }
32804
32805         me.layout = Ext.applyIf(Ext.isString(me.layout) ? {
32806             type: me.layout
32807         } : me.layout || {}, {
32808             type: me.vertical ? 'vbox' : 'hbox',
32809             align: me.vertical ? 'stretchmax' : 'middle',
32810             clearInnerCtOnLayout: true
32811         });
32812
32813         if (me.vertical) {
32814             me.addClsWithUI('vertical');
32815         }
32816
32817         
32818         if (me.ui === 'footer') {
32819             me.ignoreBorderManagement = true;
32820         }
32821
32822         me.callParent();
32823
32824         
32825         me.addEvents('overflowchange');
32826
32827         
32828         keys = me.vertical ? ['up', 'down'] : ['left', 'right'];
32829         Ext.FocusManager.subscribe(me, {
32830             keys: keys
32831         });
32832     },
32833
32834     getRefItems: function(deep) {
32835         var me = this,
32836             items = me.callParent(arguments),
32837             layout = me.layout,
32838             handler;
32839
32840         if (deep && me.enableOverflow) {
32841             handler = layout.overflowHandler;
32842             if (handler && handler.menu) {
32843                 items = items.concat(handler.menu.getRefItems(deep));
32844             }
32845         }
32846         return items;
32847     },
32848
32849     
32850
32851     
32852     lookupComponent: function(c) {
32853         if (Ext.isString(c)) {
32854             var shortcut = Ext.toolbar.Toolbar.shortcuts[c];
32855             if (shortcut) {
32856                 c = {
32857                     xtype: shortcut
32858                 };
32859             } else {
32860                 c = {
32861                     xtype: 'tbtext',
32862                     text: c
32863                 };
32864             }
32865             this.applyDefaults(c);
32866         }
32867         return this.callParent(arguments);
32868     },
32869
32870     
32871     applyDefaults: function(c) {
32872         if (!Ext.isString(c)) {
32873             c = this.callParent(arguments);
32874             var d = this.internalDefaults;
32875             if (c.events) {
32876                 Ext.applyIf(c.initialConfig, d);
32877                 Ext.apply(c, d);
32878             } else {
32879                 Ext.applyIf(c, d);
32880             }
32881         }
32882         return c;
32883     },
32884
32885     
32886     trackMenu: function(item, remove) {
32887         if (this.trackMenus && item.menu) {
32888             var method = remove ? 'mun' : 'mon',
32889                 me = this;
32890
32891             me[method](item, 'mouseover', me.onButtonOver, me);
32892             me[method](item, 'menushow', me.onButtonMenuShow, me);
32893             me[method](item, 'menuhide', me.onButtonMenuHide, me);
32894         }
32895     },
32896
32897     
32898     constructButton: function(item) {
32899         return item.events ? item : this.createComponent(item, item.split ? 'splitbutton' : this.defaultType);
32900     },
32901
32902     
32903     onBeforeAdd: function(component) {
32904         if (component.is('field') || (component.is('button') && this.ui != 'footer')) {
32905             component.ui = component.ui + '-toolbar';
32906         }
32907
32908         
32909         if (component instanceof Ext.toolbar.Separator) {
32910             component.setUI((this.vertical) ? 'vertical' : 'horizontal');
32911         }
32912
32913         this.callParent(arguments);
32914     },
32915
32916     
32917     onAdd: function(component) {
32918         this.callParent(arguments);
32919
32920         this.trackMenu(component);
32921         if (this.disabled) {
32922             component.disable();
32923         }
32924     },
32925
32926     
32927     onRemove: function(c) {
32928         this.callParent(arguments);
32929         this.trackMenu(c, true);
32930     },
32931
32932     
32933     onButtonOver: function(btn){
32934         if (this.activeMenuBtn && this.activeMenuBtn != btn) {
32935             this.activeMenuBtn.hideMenu();
32936             btn.showMenu();
32937             this.activeMenuBtn = btn;
32938         }
32939     },
32940
32941     
32942     onButtonMenuShow: function(btn) {
32943         this.activeMenuBtn = btn;
32944     },
32945
32946     
32947     onButtonMenuHide: function(btn) {
32948         delete this.activeMenuBtn;
32949     }
32950 }, function() {
32951     this.shortcuts = {
32952         '-' : 'tbseparator',
32953         ' ' : 'tbspacer',
32954         '->': 'tbfill'
32955     };
32956 });
32957
32958 Ext.define('Ext.panel.AbstractPanel', {
32959
32960     
32961
32962     extend: 'Ext.container.Container',
32963
32964     requires: ['Ext.util.MixedCollection', 'Ext.Element', 'Ext.toolbar.Toolbar'],
32965
32966     
32967
32968     
32969     baseCls : Ext.baseCSSPrefix + 'panel',
32970
32971     
32972
32973     
32974
32975     
32976
32977     
32978
32979     isPanel: true,
32980
32981     componentLayout: 'dock',
32982
32983     
32984     defaultDockWeights: { top: 1, left: 3, right: 5, bottom: 7 },
32985
32986     renderTpl: [
32987         '<div id="{id}-body" class="{baseCls}-body<tpl if="bodyCls"> {bodyCls}</tpl>',
32988             ' {baseCls}-body-{ui}<tpl if="uiCls">',
32989                 '<tpl for="uiCls"> {parent.baseCls}-body-{parent.ui}-{.}</tpl>',
32990             '</tpl>"<tpl if="bodyStyle"> style="{bodyStyle}"</tpl>>',
32991         '</div>'
32992     ],
32993
32994     
32995     
32996
32997     border: true,
32998
32999     initComponent : function() {
33000         var me = this;
33001
33002         me.addEvents(
33003             
33004             'bodyresize'
33005             
33006             
33007             
33008             
33009         );
33010
33011         me.addChildEls('body');
33012
33013         
33014         
33015
33016         if (me.frame && me.border && me.bodyBorder === undefined) {
33017             me.bodyBorder = false;
33018         }
33019         if (me.frame && me.border && (me.bodyBorder === false || me.bodyBorder === 0)) {
33020             me.manageBodyBorders = true;
33021         }
33022
33023         me.callParent();
33024     },
33025
33026     
33027     initItems : function() {
33028         var me = this,
33029             items = me.dockedItems;
33030
33031         me.callParent();
33032         me.dockedItems = Ext.create('Ext.util.MixedCollection', false, me.getComponentId);
33033         if (items) {
33034             me.addDocked(items);
33035         }
33036     },
33037
33038     
33039     getDockedComponent: function(comp) {
33040         if (Ext.isObject(comp)) {
33041             comp = comp.getItemId();
33042         }
33043         return this.dockedItems.get(comp);
33044     },
33045
33046     
33047     getComponent: function(comp) {
33048         var component = this.callParent(arguments);
33049         if (component === undefined && !Ext.isNumber(comp)) {
33050             
33051             component = this.getDockedComponent(comp);
33052         }
33053         return component;
33054     },
33055
33056     
33057     initBodyStyles: function() {
33058         var me = this,
33059             bodyStyle = me.bodyStyle,
33060             styles = [],
33061             Element = Ext.Element,
33062             prop;
33063
33064         if (Ext.isFunction(bodyStyle)) {
33065             bodyStyle = bodyStyle();
33066         }
33067         if (Ext.isString(bodyStyle)) {
33068             styles = bodyStyle.split(';');
33069         } else {
33070             for (prop in bodyStyle) {
33071                 if (bodyStyle.hasOwnProperty(prop)) {
33072                     styles.push(prop + ':' + bodyStyle[prop]);
33073                 }
33074             }
33075         }
33076
33077         if (me.bodyPadding !== undefined) {
33078             styles.push('padding: ' + Element.unitizeBox((me.bodyPadding === true) ? 5 : me.bodyPadding));
33079         }
33080         if (me.frame && me.bodyBorder) {
33081             if (!Ext.isNumber(me.bodyBorder)) {
33082                 me.bodyBorder = 1;
33083             }
33084             styles.push('border-width: ' + Element.unitizeBox(me.bodyBorder));
33085         }
33086         delete me.bodyStyle;
33087         return styles.length ? styles.join(';') : undefined;
33088     },
33089
33090     
33091     initBodyCls: function() {
33092         var me = this,
33093             cls = '',
33094             bodyCls = me.bodyCls;
33095
33096         if (bodyCls) {
33097             Ext.each(bodyCls, function(v) {
33098                 cls += " " + v;
33099             });
33100             delete me.bodyCls;
33101         }
33102         return cls.length > 0 ? cls : undefined;
33103     },
33104
33105     
33106     initRenderData: function() {
33107         return Ext.applyIf(this.callParent(), {
33108             bodyStyle: this.initBodyStyles(),
33109             bodyCls: this.initBodyCls()
33110         });
33111     },
33112
33113     
33114     addDocked : function(items, pos) {
33115         var me = this,
33116             i = 0,
33117             item, length;
33118
33119         items = me.prepareItems(items);
33120         length = items.length;
33121
33122         for (; i < length; i++) {
33123             item = items[i];
33124             item.dock = item.dock || 'top';
33125
33126             
33127             if (me.border === false) {
33128                 
33129             }
33130
33131             if (pos !== undefined) {
33132                 me.dockedItems.insert(pos + i, item);
33133             }
33134             else {
33135                 me.dockedItems.add(item);
33136             }
33137             item.onAdded(me, i);
33138             me.onDockedAdd(item);
33139         }
33140
33141         
33142         me.componentLayout.childrenChanged = true;
33143         if (me.rendered && !me.suspendLayout) {
33144             me.doComponentLayout();
33145         }
33146         return items;
33147     },
33148
33149     
33150     onDockedAdd : Ext.emptyFn,
33151     onDockedRemove : Ext.emptyFn,
33152
33153     
33154     insertDocked : function(pos, items) {
33155         this.addDocked(items, pos);
33156     },
33157
33158     
33159     removeDocked : function(item, autoDestroy) {
33160         var me = this,
33161             layout,
33162             hasLayout;
33163
33164         if (!me.dockedItems.contains(item)) {
33165             return item;
33166         }
33167
33168         layout = me.componentLayout;
33169         hasLayout = layout && me.rendered;
33170
33171         if (hasLayout) {
33172             layout.onRemove(item);
33173         }
33174
33175         me.dockedItems.remove(item);
33176         item.onRemoved();
33177         me.onDockedRemove(item);
33178
33179         if (autoDestroy === true || (autoDestroy !== false && me.autoDestroy)) {
33180             item.destroy();
33181         } else if (hasLayout) {
33182             
33183             layout.afterRemove(item);    
33184         }
33185
33186
33187         
33188         me.componentLayout.childrenChanged = true;
33189         if (!me.destroying && !me.suspendLayout) {
33190             me.doComponentLayout();
33191         }
33192
33193         return item;
33194     },
33195
33196     
33197     getDockedItems : function(cqSelector) {
33198         var me = this,
33199             defaultWeight = me.defaultDockWeights,
33200             dockedItems;
33201
33202         if (me.dockedItems && me.dockedItems.items.length) {
33203             
33204             if (cqSelector) {
33205                 dockedItems = Ext.ComponentQuery.query(cqSelector, me.dockedItems.items);
33206             } else {
33207                 dockedItems = me.dockedItems.items.slice();
33208             }
33209
33210             Ext.Array.sort(dockedItems, function(a, b) {
33211                 
33212                 var aw = a.weight || defaultWeight[a.dock],
33213                     bw = b.weight || defaultWeight[b.dock];
33214                 if (Ext.isNumber(aw) && Ext.isNumber(bw)) {
33215                     return aw - bw;
33216                 }
33217                 return 0;
33218             });
33219
33220             return dockedItems;
33221         }
33222         return [];
33223     },
33224
33225     
33226     addUIClsToElement: function(cls, force) {
33227         var me = this,
33228             result = me.callParent(arguments),
33229             classes = [Ext.baseCSSPrefix + cls, me.baseCls + '-body-' + cls, me.baseCls + '-body-' + me.ui + '-' + cls],
33230             array, i;
33231
33232         if (!force && me.rendered) {
33233             if (me.bodyCls) {
33234                 me.body.addCls(me.bodyCls);
33235             } else {
33236                 me.body.addCls(classes);
33237             }
33238         } else {
33239             if (me.bodyCls) {
33240                 array = me.bodyCls.split(' ');
33241
33242                 for (i = 0; i < classes.length; i++) {
33243                     if (!Ext.Array.contains(array, classes[i])) {
33244                         array.push(classes[i]);
33245                     }
33246                 }
33247
33248                 me.bodyCls = array.join(' ');
33249             } else {
33250                 me.bodyCls = classes.join(' ');
33251             }
33252         }
33253
33254         return result;
33255     },
33256
33257     
33258     removeUIClsFromElement: function(cls, force) {
33259         var me = this,
33260             result = me.callParent(arguments),
33261             classes = [Ext.baseCSSPrefix + cls, me.baseCls + '-body-' + cls, me.baseCls + '-body-' + me.ui + '-' + cls],
33262             array, i;
33263
33264         if (!force && me.rendered) {
33265             if (me.bodyCls) {
33266                 me.body.removeCls(me.bodyCls);
33267             } else {
33268                 me.body.removeCls(classes);
33269             }
33270         } else {
33271             if (me.bodyCls) {
33272                 array = me.bodyCls.split(' ');
33273
33274                 for (i = 0; i < classes.length; i++) {
33275                     Ext.Array.remove(array, classes[i]);
33276                 }
33277
33278                 me.bodyCls = array.join(' ');
33279             }
33280         }
33281
33282         return result;
33283     },
33284
33285     
33286     addUIToElement: function(force) {
33287         var me = this,
33288             cls = me.baseCls + '-body-' + me.ui,
33289             array;
33290
33291         me.callParent(arguments);
33292
33293         if (!force && me.rendered) {
33294             if (me.bodyCls) {
33295                 me.body.addCls(me.bodyCls);
33296             } else {
33297                 me.body.addCls(cls);
33298             }
33299         } else {
33300             if (me.bodyCls) {
33301                 array = me.bodyCls.split(' ');
33302
33303                 if (!Ext.Array.contains(array, cls)) {
33304                     array.push(cls);
33305                 }
33306
33307                 me.bodyCls = array.join(' ');
33308             } else {
33309                 me.bodyCls = cls;
33310             }
33311         }
33312     },
33313
33314     
33315     removeUIFromElement: function() {
33316         var me = this,
33317             cls = me.baseCls + '-body-' + me.ui,
33318             array;
33319
33320         me.callParent(arguments);
33321
33322         if (me.rendered) {
33323             if (me.bodyCls) {
33324                 me.body.removeCls(me.bodyCls);
33325             } else {
33326                 me.body.removeCls(cls);
33327             }
33328         } else {
33329             if (me.bodyCls) {
33330                 array = me.bodyCls.split(' ');
33331                 Ext.Array.remove(array, cls);
33332                 me.bodyCls = array.join(' ');
33333             } else {
33334                 me.bodyCls = cls;
33335             }
33336         }
33337     },
33338
33339     
33340     getTargetEl : function() {
33341         return this.body;
33342     },
33343
33344     getRefItems: function(deep) {
33345         var items = this.callParent(arguments),
33346             
33347             dockedItems = this.getDockedItems(deep ? '*,* *' : undefined),
33348             ln = dockedItems.length,
33349             i = 0,
33350             item;
33351
33352         
33353         for (; i < ln; i++) {
33354             item = dockedItems[i];
33355             if (item.dock === 'right' || item.dock === 'bottom') {
33356                 break;
33357             }
33358         }
33359
33360         
33361         
33362         
33363         return Ext.Array.splice(dockedItems, 0, i).concat(items).concat(dockedItems);
33364     },
33365
33366     beforeDestroy: function(){
33367         var docked = this.dockedItems,
33368             c;
33369
33370         if (docked) {
33371             while ((c = docked.first())) {
33372                 this.removeDocked(c, true);
33373             }
33374         }
33375         this.callParent();
33376     },
33377
33378     setBorder: function(border) {
33379         var me = this;
33380         me.border = (border !== undefined) ? border : true;
33381         if (me.rendered) {
33382             me.doComponentLayout();
33383         }
33384     }
33385 });
33386
33387 Ext.define('Ext.panel.Header', {
33388     extend: 'Ext.container.Container',
33389     uses: ['Ext.panel.Tool', 'Ext.draw.Component', 'Ext.util.CSS'],
33390     alias: 'widget.header',
33391
33392     isHeader       : true,
33393     defaultType    : 'tool',
33394     indicateDrag   : false,
33395     weight         : -1,
33396
33397     renderTpl: [
33398         '<div id="{id}-body" class="{baseCls}-body<tpl if="bodyCls"> {bodyCls}</tpl>',
33399         '<tpl if="uiCls">',
33400             '<tpl for="uiCls"> {parent.baseCls}-body-{parent.ui}-{.}</tpl>',
33401         '</tpl>"',
33402         '<tpl if="bodyStyle"> style="{bodyStyle}"</tpl>></div>'],
33403
33404     
33405
33406     
33407
33408     initComponent: function() {
33409         var me = this,
33410             ruleStyle,
33411             rule,
33412             style,
33413             titleTextEl,
33414             ui;
33415
33416         me.indicateDragCls = me.baseCls + '-draggable';
33417         me.title = me.title || '&#160;';
33418         me.tools = me.tools || [];
33419         me.items = me.items || [];
33420         me.orientation = me.orientation || 'horizontal';
33421         me.dock = (me.dock) ? me.dock : (me.orientation == 'horizontal') ? 'top' : 'left';
33422
33423         
33424         
33425         me.addClsWithUI(me.orientation);
33426         me.addClsWithUI(me.dock);
33427
33428         me.addChildEls('body');
33429
33430         
33431         if (!Ext.isEmpty(me.iconCls)) {
33432             me.initIconCmp();
33433             me.items.push(me.iconCmp);
33434         }
33435
33436         
33437         if (me.orientation == 'vertical') {
33438             
33439             if (Ext.isIE6 || Ext.isIE7) {
33440                 me.width = this.width || 24;
33441             } else if (Ext.isIEQuirks) {
33442                 me.width = this.width || 25;
33443             }
33444
33445             me.layout = {
33446                 type : 'vbox',
33447                 align: 'center',
33448                 clearInnerCtOnLayout: true,
33449                 bindToOwnerCtContainer: false
33450             };
33451             me.textConfig = {
33452                 cls: me.baseCls + '-text',
33453                 type: 'text',
33454                 text: me.title,
33455                 rotate: {
33456                     degrees: 90
33457                 }
33458             };
33459             ui = me.ui;
33460             if (Ext.isArray(ui)) {
33461                 ui = ui[0];
33462             }
33463             ruleStyle = '.' + me.baseCls + '-text-' + ui;
33464             if (Ext.scopeResetCSS) {
33465                 ruleStyle = '.' + Ext.baseCSSPrefix + 'reset ' + ruleStyle;
33466             }
33467             rule = Ext.util.CSS.getRule(ruleStyle);
33468             if (rule) {
33469                 style = rule.style;
33470             }
33471             if (style) {
33472                 Ext.apply(me.textConfig, {
33473                     'font-family': style.fontFamily,
33474                     'font-weight': style.fontWeight,
33475                     'font-size': style.fontSize,
33476                     fill: style.color
33477                 });
33478             }
33479             me.titleCmp = Ext.create('Ext.draw.Component', {
33480                 ariaRole  : 'heading',
33481                 focusable: false,
33482                 viewBox: false,
33483                 flex : 1,
33484                 autoSize: true,
33485                 margins: '5 0 0 0',
33486                 items: [ me.textConfig ],
33487                 
33488                 
33489                 renderSelectors: {
33490                     textEl: '.' + me.baseCls + '-text'
33491                 }
33492             });
33493         } else {
33494             me.layout = {
33495                 type : 'hbox',
33496                 align: 'middle',
33497                 clearInnerCtOnLayout: true,
33498                 bindToOwnerCtContainer: false
33499             };
33500             me.titleCmp = Ext.create('Ext.Component', {
33501                 xtype     : 'component',
33502                 ariaRole  : 'heading',
33503                 focusable: false,
33504                 flex : 1,
33505                 cls: me.baseCls + '-text-container',
33506                 renderTpl : [
33507                     '<span id="{id}-textEl" class="{cls}-text {cls}-text-{ui}">{title}</span>'
33508                 ],
33509                 renderData: {
33510                     title: me.title,
33511                     cls  : me.baseCls,
33512                     ui   : me.ui
33513                 },
33514                 childEls: ['textEl']
33515             });
33516         }
33517         me.items.push(me.titleCmp);
33518
33519         
33520         me.items = me.items.concat(me.tools);
33521         this.callParent();
33522     },
33523
33524     initIconCmp: function() {
33525         this.iconCmp = Ext.create('Ext.Component', {
33526             focusable: false,
33527             renderTpl : [
33528                 '<img id="{id}-iconEl" alt="" src="{blank}" class="{cls}-icon {iconCls}"/>'
33529             ],
33530             renderData: {
33531                 blank  : Ext.BLANK_IMAGE_URL,
33532                 cls    : this.baseCls,
33533                 iconCls: this.iconCls,
33534                 orientation: this.orientation
33535             },
33536             childEls: ['iconEl'],
33537             iconCls: this.iconCls
33538         });
33539     },
33540
33541     afterRender: function() {
33542         var me = this;
33543
33544         me.el.unselectable();
33545         if (me.indicateDrag) {
33546             me.el.addCls(me.indicateDragCls);
33547         }
33548         me.mon(me.el, {
33549             click: me.onClick,
33550             scope: me
33551         });
33552         me.callParent();
33553     },
33554
33555     afterLayout: function() {
33556         var me = this;
33557         me.callParent(arguments);
33558
33559         
33560         if (Ext.isIE7) {
33561             me.el.repaint();
33562         }
33563     },
33564
33565     
33566     addUIClsToElement: function(cls, force) {
33567         var me = this,
33568             result = me.callParent(arguments),
33569             classes = [me.baseCls + '-body-' + cls, me.baseCls + '-body-' + me.ui + '-' + cls],
33570             array, i;
33571
33572         if (!force && me.rendered) {
33573             if (me.bodyCls) {
33574                 me.body.addCls(me.bodyCls);
33575             } else {
33576                 me.body.addCls(classes);
33577             }
33578         } else {
33579             if (me.bodyCls) {
33580                 array = me.bodyCls.split(' ');
33581
33582                 for (i = 0; i < classes.length; i++) {
33583                     if (!Ext.Array.contains(array, classes[i])) {
33584                         array.push(classes[i]);
33585                     }
33586                 }
33587
33588                 me.bodyCls = array.join(' ');
33589             } else {
33590                 me.bodyCls = classes.join(' ');
33591             }
33592         }
33593
33594         return result;
33595     },
33596
33597     
33598     removeUIClsFromElement: function(cls, force) {
33599         var me = this,
33600             result = me.callParent(arguments),
33601             classes = [me.baseCls + '-body-' + cls, me.baseCls + '-body-' + me.ui + '-' + cls],
33602             array, i;
33603
33604         if (!force && me.rendered) {
33605             if (me.bodyCls) {
33606                 me.body.removeCls(me.bodyCls);
33607             } else {
33608                 me.body.removeCls(classes);
33609             }
33610         } else {
33611             if (me.bodyCls) {
33612                 array = me.bodyCls.split(' ');
33613
33614                 for (i = 0; i < classes.length; i++) {
33615                     Ext.Array.remove(array, classes[i]);
33616                 }
33617
33618                 me.bodyCls = array.join(' ');
33619             }
33620         }
33621
33622        return result;
33623     },
33624
33625     
33626     addUIToElement: function(force) {
33627         var me = this,
33628             array, cls;
33629
33630         me.callParent(arguments);
33631
33632         cls = me.baseCls + '-body-' + me.ui;
33633         if (!force && me.rendered) {
33634             if (me.bodyCls) {
33635                 me.body.addCls(me.bodyCls);
33636             } else {
33637                 me.body.addCls(cls);
33638             }
33639         } else {
33640             if (me.bodyCls) {
33641                 array = me.bodyCls.split(' ');
33642
33643                 if (!Ext.Array.contains(array, cls)) {
33644                     array.push(cls);
33645                 }
33646
33647                 me.bodyCls = array.join(' ');
33648             } else {
33649                 me.bodyCls = cls;
33650             }
33651         }
33652
33653         if (!force && me.titleCmp && me.titleCmp.rendered && me.titleCmp.textEl) {
33654             me.titleCmp.textEl.addCls(me.baseCls + '-text-' + me.ui);
33655         }
33656     },
33657
33658     
33659     removeUIFromElement: function() {
33660         var me = this,
33661             array, cls;
33662
33663         me.callParent(arguments);
33664
33665         cls = me.baseCls + '-body-' + me.ui;
33666         if (me.rendered) {
33667             if (me.bodyCls) {
33668                 me.body.removeCls(me.bodyCls);
33669             } else {
33670                 me.body.removeCls(cls);
33671             }
33672         } else {
33673             if (me.bodyCls) {
33674                 array = me.bodyCls.split(' ');
33675                 Ext.Array.remove(array, cls);
33676                 me.bodyCls = array.join(' ');
33677             } else {
33678                 me.bodyCls = cls;
33679             }
33680         }
33681
33682         if (me.titleCmp && me.titleCmp.rendered && me.titleCmp.textEl) {
33683             me.titleCmp.textEl.removeCls(me.baseCls + '-text-' + me.ui);
33684         }
33685     },
33686
33687     onClick: function(e) {
33688         if (!e.getTarget(Ext.baseCSSPrefix + 'tool')) {
33689             this.fireEvent('click', e);
33690         }
33691     },
33692
33693     getTargetEl: function() {
33694         return this.body || this.frameBody || this.el;
33695     },
33696
33697     
33698     setTitle: function(title) {
33699         var me = this;
33700         if (me.rendered) {
33701             if (me.titleCmp.rendered) {
33702                 if (me.titleCmp.surface) {
33703                     me.title = title || '';
33704                     var sprite = me.titleCmp.surface.items.items[0],
33705                         surface = me.titleCmp.surface;
33706
33707                     surface.remove(sprite);
33708                     me.textConfig.type = 'text';
33709                     me.textConfig.text = title;
33710                     sprite = surface.add(me.textConfig);
33711                     sprite.setAttributes({
33712                         rotate: {
33713                             degrees: 90
33714                         }
33715                     }, true);
33716                     me.titleCmp.autoSizeSurface();
33717                 } else {
33718                     me.title = title || '&#160;';
33719                     me.titleCmp.textEl.update(me.title);
33720                 }
33721             } else {
33722                 me.titleCmp.on({
33723                     render: function() {
33724                         me.setTitle(title);
33725                     },
33726                     single: true
33727                 });
33728             }
33729         } else {
33730             me.on({
33731                 render: function() {
33732                     me.layout.layout();
33733                     me.setTitle(title);
33734                 },
33735                 single: true
33736             });
33737         }
33738     },
33739
33740     
33741     setIconCls: function(cls) {
33742         var me = this,
33743             isEmpty = !cls || !cls.length,
33744             iconCmp = me.iconCmp,
33745             el;
33746         
33747         me.iconCls = cls;
33748         if (!me.iconCmp && !isEmpty) {
33749             me.initIconCmp();
33750             me.insert(0, me.iconCmp);
33751         } else if (iconCmp) {
33752             if (isEmpty) {
33753                 me.iconCmp.destroy();
33754             } else {
33755                 el = iconCmp.iconEl;
33756                 el.removeCls(iconCmp.iconCls);
33757                 el.addCls(cls);
33758                 iconCmp.iconCls = cls;
33759             }
33760         }
33761     },
33762
33763     
33764     addTool: function(tool) {
33765         this.tools.push(this.add(tool));
33766     },
33767
33768     
33769     onAdd: function(component, index) {
33770         this.callParent([arguments]);
33771         if (component instanceof Ext.panel.Tool) {
33772             component.bindTo(this.ownerCt);
33773             this.tools[component.type] = component;
33774         }
33775     }
33776 });
33777
33778
33779 Ext.define('Ext.fx.target.Element', {
33780
33781     
33782     
33783     extend: 'Ext.fx.target.Target',
33784     
33785     
33786
33787     type: 'element',
33788
33789     getElVal: function(el, attr, val) {
33790         if (val == undefined) {
33791             if (attr === 'x') {
33792                 val = el.getX();
33793             }
33794             else if (attr === 'y') {
33795                 val = el.getY();
33796             }
33797             else if (attr === 'scrollTop') {
33798                 val = el.getScroll().top;
33799             }
33800             else if (attr === 'scrollLeft') {
33801                 val = el.getScroll().left;
33802             }
33803             else if (attr === 'height') {
33804                 val = el.getHeight();
33805             }
33806             else if (attr === 'width') {
33807                 val = el.getWidth();
33808             }
33809             else {
33810                 val = el.getStyle(attr);
33811             }
33812         }
33813         return val;
33814     },
33815
33816     getAttr: function(attr, val) {
33817         var el = this.target;
33818         return [[ el, this.getElVal(el, attr, val)]];
33819     },
33820
33821     setAttr: function(targetData) {
33822         var target = this.target,
33823             ln = targetData.length,
33824             attrs, attr, o, i, j, ln2, element, value;
33825         for (i = 0; i < ln; i++) {
33826             attrs = targetData[i].attrs;
33827             for (attr in attrs) {
33828                 if (attrs.hasOwnProperty(attr)) {
33829                     ln2 = attrs[attr].length;
33830                     for (j = 0; j < ln2; j++) {
33831                         o = attrs[attr][j];
33832                         element = o[0];
33833                         value = o[1];
33834                         if (attr === 'x') {
33835                             element.setX(value);
33836                         }
33837                         else if (attr === 'y') {
33838                             element.setY(value);
33839                         }
33840                         else if (attr === 'scrollTop') {
33841                             element.scrollTo('top', value);
33842                         }
33843                         else if (attr === 'scrollLeft') {
33844                             element.scrollTo('left',value);
33845                         }
33846                         else {
33847                             element.setStyle(attr, value);
33848                         }
33849                     }
33850                 }
33851             }
33852         }
33853     }
33854 });
33855
33856
33857 Ext.define('Ext.fx.target.CompositeElement', {
33858
33859     
33860
33861     extend: 'Ext.fx.target.Element',
33862
33863     
33864
33865     isComposite: true,
33866     
33867     constructor: function(target) {
33868         target.id = target.id || Ext.id(null, 'ext-composite-');
33869         this.callParent([target]);
33870     },
33871
33872     getAttr: function(attr, val) {
33873         var out = [],
33874             target = this.target;
33875         target.each(function(el) {
33876             out.push([el, this.getElVal(el, attr, val)]);
33877         }, this);
33878         return out;
33879     }
33880 });
33881
33882
33883
33884 Ext.define('Ext.fx.Manager', {
33885
33886     
33887
33888     singleton: true,
33889
33890     requires: ['Ext.util.MixedCollection',
33891                'Ext.fx.target.Element',
33892                'Ext.fx.target.CompositeElement',
33893                'Ext.fx.target.Sprite',
33894                'Ext.fx.target.CompositeSprite',
33895                'Ext.fx.target.Component'],
33896
33897     mixins: {
33898         queue: 'Ext.fx.Queue'
33899     },
33900
33901     
33902
33903     constructor: function() {
33904         this.items = Ext.create('Ext.util.MixedCollection');
33905         this.mixins.queue.constructor.call(this);
33906
33907         
33908         
33909         
33910         
33911         
33912         
33913         
33914         
33915         
33916         
33917         
33918         
33919         
33920         
33921         
33922         
33923         
33924     },
33925
33926     
33927     interval: 16,
33928
33929     
33930     forceJS: true,
33931
33932     
33933     createTarget: function(target) {
33934         var me = this,
33935             useCSS3 = !me.forceJS && Ext.supports.Transitions,
33936             targetObj;
33937
33938         me.useCSS3 = useCSS3;
33939
33940         
33941         if (Ext.isString(target)) {
33942             target = Ext.get(target);
33943         }
33944         
33945         if (target && target.tagName) {
33946             target = Ext.get(target);
33947             targetObj = Ext.create('Ext.fx.target.' + 'Element' + (useCSS3 ? 'CSS' : ''), target);
33948             me.targets.add(targetObj);
33949             return targetObj;
33950         }
33951         if (Ext.isObject(target)) {
33952             
33953             if (target.dom) {
33954                 targetObj = Ext.create('Ext.fx.target.' + 'Element' + (useCSS3 ? 'CSS' : ''), target);
33955             }
33956             
33957             else if (target.isComposite) {
33958                 targetObj = Ext.create('Ext.fx.target.' + 'CompositeElement' + (useCSS3 ? 'CSS' : ''), target);
33959             }
33960             
33961             else if (target.isSprite) {
33962                 targetObj = Ext.create('Ext.fx.target.Sprite', target);
33963             }
33964             
33965             else if (target.isCompositeSprite) {
33966                 targetObj = Ext.create('Ext.fx.target.CompositeSprite', target);
33967             }
33968             
33969             else if (target.isComponent) {
33970                 targetObj = Ext.create('Ext.fx.target.Component', target);
33971             }
33972             else if (target.isAnimTarget) {
33973                 return target;
33974             }
33975             else {
33976                 return null;
33977             }
33978             me.targets.add(targetObj);
33979             return targetObj;
33980         }
33981         else {
33982             return null;
33983         }
33984     },
33985
33986     
33987     addAnim: function(anim) {
33988         var items = this.items,
33989             task = this.task;
33990         
33991         
33992         
33993         
33994         
33995         
33996         
33997         
33998         
33999         
34000         
34001         
34002
34003         items.add(anim);
34004
34005         
34006         if (!task && items.length) {
34007             task = this.task = {
34008                 run: this.runner,
34009                 interval: this.interval,
34010                 scope: this
34011             };
34012             Ext.TaskManager.start(task);
34013         }
34014
34015         
34016         
34017         
34018         
34019     },
34020
34021     
34022     removeAnim: function(anim) {
34023         
34024         var items = this.items,
34025             task = this.task;
34026         items.remove(anim);
34027         
34028         if (task && !items.length) {
34029             Ext.TaskManager.stop(task);
34030             delete this.task;
34031         }
34032     },
34033
34034     
34035     startingFilter: function(o) {
34036         return o.paused === false && o.running === false && o.iterations > 0;
34037     },
34038
34039     
34040     runningFilter: function(o) {
34041         return o.paused === false && o.running === true && o.isAnimator !== true;
34042     },
34043
34044     
34045     runner: function() {
34046         var me = this,
34047             items = me.items;
34048
34049         me.targetData = {};
34050         me.targetArr = {};
34051
34052         
34053         me.timestamp = new Date();
34054
34055         
34056         items.filterBy(me.startingFilter).each(me.startAnim, me);
34057
34058         
34059         items.filterBy(me.runningFilter).each(me.runAnim, me);
34060
34061         
34062         me.applyPendingAttrs();
34063     },
34064
34065     
34066     startAnim: function(anim) {
34067         anim.start(this.timestamp);
34068     },
34069
34070     
34071     runAnim: function(anim) {
34072         if (!anim) {
34073             return;
34074         }
34075         var me = this,
34076             targetId = anim.target.getId(),
34077             useCSS3 = me.useCSS3 && anim.target.type == 'element',
34078             elapsedTime = me.timestamp - anim.startTime,
34079             target, o;
34080
34081         this.collectTargetData(anim, elapsedTime, useCSS3);
34082
34083         
34084         
34085         if (useCSS3) {
34086             
34087             anim.target.setAttr(me.targetData[targetId], true);
34088
34089             
34090             me.targetData[targetId] = [];
34091             me.collectTargetData(anim, anim.duration, useCSS3);
34092
34093             
34094             anim.paused = true;
34095
34096             target = anim.target.target;
34097             
34098             if (anim.target.isComposite) {
34099                 target = anim.target.target.last();
34100             }
34101
34102             
34103             o = {};
34104             o[Ext.supports.CSS3TransitionEnd] = anim.lastFrame;
34105             o.scope = anim;
34106             o.single = true;
34107             target.on(o);
34108         }
34109         
34110         else if (elapsedTime >= anim.duration) {
34111             me.applyPendingAttrs(true);
34112             delete me.targetData[targetId];
34113             delete me.targetArr[targetId];
34114             anim.lastFrame();
34115         }
34116     },
34117
34118     
34119     collectTargetData: function(anim, elapsedTime, useCSS3) {
34120         var targetId = anim.target.getId(),
34121             targetData = this.targetData[targetId],
34122             data;
34123         
34124         if (!targetData) {
34125             targetData = this.targetData[targetId] = [];
34126             this.targetArr[targetId] = anim.target;
34127         }
34128
34129         data = {
34130             duration: anim.duration,
34131             easing: (useCSS3 && anim.reverse) ? anim.easingFn.reverse().toCSS3() : anim.easing,
34132             attrs: {}
34133         };
34134         Ext.apply(data.attrs, anim.runAnim(elapsedTime));
34135         targetData.push(data);
34136     },
34137
34138     
34139     applyPendingAttrs: function(isLastFrame) {
34140         var targetData = this.targetData,
34141             targetArr = this.targetArr,
34142             targetId;
34143         for (targetId in targetData) {
34144             if (targetData.hasOwnProperty(targetId)) {
34145                 targetArr[targetId].setAttr(targetData[targetId], false, isLastFrame);
34146             }
34147         }
34148     }
34149 });
34150
34151
34152 Ext.define('Ext.fx.Animator', {
34153
34154     
34155
34156     mixins: {
34157         observable: 'Ext.util.Observable'
34158     },
34159
34160     requires: ['Ext.fx.Manager'],
34161
34162     
34163
34164     isAnimator: true,
34165
34166     
34167     duration: 250,
34168
34169     
34170     delay: 0,
34171
34172     
34173     delayStart: 0,
34174
34175     
34176     dynamic: false,
34177
34178     
34179     easing: 'ease',
34180
34181     
34182     running: false,
34183
34184     
34185     paused: false,
34186
34187     
34188     damper: 1,
34189
34190     
34191     iterations: 1,
34192
34193     
34194     currentIteration: 0,
34195
34196     
34197     keyframeStep: 0,
34198
34199     
34200     animKeyFramesRE: /^(from|to|\d+%?)$/,
34201
34202     
34203
34204      
34205     constructor: function(config) {
34206         var me = this;
34207         config = Ext.apply(me, config || {});
34208         me.config = config;
34209         me.id = Ext.id(null, 'ext-animator-');
34210         me.addEvents(
34211             
34212             'beforeanimate',
34213             
34214             'keyframe',
34215             
34216             'afteranimate'
34217         );
34218         me.mixins.observable.constructor.call(me, config);
34219         me.timeline = [];
34220         me.createTimeline(me.keyframes);
34221         if (me.target) {
34222             me.applyAnimator(me.target);
34223             Ext.fx.Manager.addAnim(me);
34224         }
34225     },
34226
34227     
34228     sorter: function (a, b) {
34229         return a.pct - b.pct;
34230     },
34231
34232     
34233     createTimeline: function(keyframes) {
34234         var me = this,
34235             attrs = [],
34236             to = me.to || {},
34237             duration = me.duration,
34238             prevMs, ms, i, ln, pct, anim, nextAnim, attr;
34239
34240         for (pct in keyframes) {
34241             if (keyframes.hasOwnProperty(pct) && me.animKeyFramesRE.test(pct)) {
34242                 attr = {attrs: Ext.apply(keyframes[pct], to)};
34243                 
34244                 if (pct == "from") {
34245                     pct = 0;
34246                 }
34247                 else if (pct == "to") {
34248                     pct = 100;
34249                 }
34250                 
34251                 attr.pct = parseInt(pct, 10);
34252                 attrs.push(attr);
34253             }
34254         }
34255         
34256         Ext.Array.sort(attrs, me.sorter);
34257         
34258         
34259         
34260         
34261
34262         ln = attrs.length;
34263         for (i = 0; i < ln; i++) {
34264             prevMs = (attrs[i - 1]) ? duration * (attrs[i - 1].pct / 100) : 0;
34265             ms = duration * (attrs[i].pct / 100);
34266             me.timeline.push({
34267                 duration: ms - prevMs,
34268                 attrs: attrs[i].attrs
34269             });
34270         }
34271     },
34272
34273     
34274     applyAnimator: function(target) {
34275         var me = this,
34276             anims = [],
34277             timeline = me.timeline,
34278             reverse = me.reverse,
34279             ln = timeline.length,
34280             anim, easing, damper, initial, attrs, lastAttrs, i;
34281
34282         if (me.fireEvent('beforeanimate', me) !== false) {
34283             for (i = 0; i < ln; i++) {
34284                 anim = timeline[i];
34285                 attrs = anim.attrs;
34286                 easing = attrs.easing || me.easing;
34287                 damper = attrs.damper || me.damper;
34288                 delete attrs.easing;
34289                 delete attrs.damper;
34290                 anim = Ext.create('Ext.fx.Anim', {
34291                     target: target,
34292                     easing: easing,
34293                     damper: damper,
34294                     duration: anim.duration,
34295                     paused: true,
34296                     to: attrs
34297                 });
34298                 anims.push(anim);
34299             }
34300             me.animations = anims;
34301             me.target = anim.target;
34302             for (i = 0; i < ln - 1; i++) {
34303                 anim = anims[i];
34304                 anim.nextAnim = anims[i + 1];
34305                 anim.on('afteranimate', function() {
34306                     this.nextAnim.paused = false;
34307                 });
34308                 anim.on('afteranimate', function() {
34309                     this.fireEvent('keyframe', this, ++this.keyframeStep);
34310                 }, me);
34311             }
34312             anims[ln - 1].on('afteranimate', function() {
34313                 this.lastFrame();
34314             }, me);
34315         }
34316     },
34317
34318     
34319     start: function(startTime) {
34320         var me = this,
34321             delay = me.delay,
34322             delayStart = me.delayStart,
34323             delayDelta;
34324         if (delay) {
34325             if (!delayStart) {
34326                 me.delayStart = startTime;
34327                 return;
34328             }
34329             else {
34330                 delayDelta = startTime - delayStart;
34331                 if (delayDelta < delay) {
34332                     return;
34333                 }
34334                 else {
34335                     
34336                     startTime = new Date(delayStart.getTime() + delay);
34337                 }
34338             }
34339         }
34340         if (me.fireEvent('beforeanimate', me) !== false) {
34341             me.startTime = startTime;
34342             me.running = true;
34343             me.animations[me.keyframeStep].paused = false;
34344         }
34345     },
34346
34347     
34348     lastFrame: function() {
34349         var me = this,
34350             iter = me.iterations,
34351             iterCount = me.currentIteration;
34352
34353         iterCount++;
34354         if (iterCount < iter) {
34355             me.startTime = new Date();
34356             me.currentIteration = iterCount;
34357             me.keyframeStep = 0;
34358             me.applyAnimator(me.target);
34359             me.animations[me.keyframeStep].paused = false;
34360         }
34361         else {
34362             me.currentIteration = 0;
34363             me.end();
34364         }
34365     },
34366
34367     
34368     end: function() {
34369         var me = this;
34370         me.fireEvent('afteranimate', me, me.startTime, new Date() - me.startTime);
34371     }
34372 });
34373
34374 Ext.ns('Ext.fx');
34375
34376 Ext.require('Ext.fx.CubicBezier', function() {
34377     var math = Math,
34378         pi = math.PI,
34379         pow = math.pow,
34380         sin = math.sin,
34381         sqrt = math.sqrt,
34382         abs = math.abs,
34383         backInSeed = 1.70158;
34384     Ext.fx.Easing = {
34385         
34386         
34387         
34388         
34389         
34390         
34391         
34392         
34393     };
34394
34395     Ext.apply(Ext.fx.Easing, {
34396         linear: function(n) {
34397             return n;
34398         },
34399         ease: function(n) {
34400             var q = 0.07813 - n / 2,
34401                 alpha = -0.25,
34402                 Q = sqrt(0.0066 + q * q),
34403                 x = Q - q,
34404                 X = pow(abs(x), 1/3) * (x < 0 ? -1 : 1),
34405                 y = -Q - q,
34406                 Y = pow(abs(y), 1/3) * (y < 0 ? -1 : 1),
34407                 t = X + Y + 0.25;
34408             return pow(1 - t, 2) * 3 * t * 0.1 + (1 - t) * 3 * t * t + t * t * t;
34409         },
34410         easeIn: function (n) {
34411             return pow(n, 1.7);
34412         },
34413         easeOut: function (n) {
34414             return pow(n, 0.48);
34415         },
34416         easeInOut: function(n) {
34417             var q = 0.48 - n / 1.04,
34418                 Q = sqrt(0.1734 + q * q),
34419                 x = Q - q,
34420                 X = pow(abs(x), 1/3) * (x < 0 ? -1 : 1),
34421                 y = -Q - q,
34422                 Y = pow(abs(y), 1/3) * (y < 0 ? -1 : 1),
34423                 t = X + Y + 0.5;
34424             return (1 - t) * 3 * t * t + t * t * t;
34425         },
34426         backIn: function (n) {
34427             return n * n * ((backInSeed + 1) * n - backInSeed);
34428         },
34429         backOut: function (n) {
34430             n = n - 1;
34431             return n * n * ((backInSeed + 1) * n + backInSeed) + 1;
34432         },
34433         elasticIn: function (n) {
34434             if (n === 0 || n === 1) {
34435                 return n;
34436             }
34437             var p = 0.3,
34438                 s = p / 4;
34439             return pow(2, -10 * n) * sin((n - s) * (2 * pi) / p) + 1;
34440         },
34441         elasticOut: function (n) {
34442             return 1 - Ext.fx.Easing.elasticIn(1 - n);
34443         },
34444         bounceIn: function (n) {
34445             return 1 - Ext.fx.Easing.bounceOut(1 - n);
34446         },
34447         bounceOut: function (n) {
34448             var s = 7.5625,
34449                 p = 2.75,
34450                 l;
34451             if (n < (1 / p)) {
34452                 l = s * n * n;
34453             } else {
34454                 if (n < (2 / p)) {
34455                     n -= (1.5 / p);
34456                     l = s * n * n + 0.75;
34457                 } else {
34458                     if (n < (2.5 / p)) {
34459                         n -= (2.25 / p);
34460                         l = s * n * n + 0.9375;
34461                     } else {
34462                         n -= (2.625 / p);
34463                         l = s * n * n + 0.984375;
34464                     }
34465                 }
34466             }
34467             return l;
34468         }
34469     });
34470     Ext.apply(Ext.fx.Easing, {
34471         'back-in': Ext.fx.Easing.backIn,
34472         'back-out': Ext.fx.Easing.backOut,
34473         'ease-in': Ext.fx.Easing.easeIn,
34474         'ease-out': Ext.fx.Easing.easeOut,
34475         'elastic-in': Ext.fx.Easing.elasticIn,
34476         'elastic-out': Ext.fx.Easing.elasticIn,
34477         'bounce-in': Ext.fx.Easing.bounceIn,
34478         'bounce-out': Ext.fx.Easing.bounceOut,
34479         'ease-in-out': Ext.fx.Easing.easeInOut
34480     });
34481 });
34482
34483 Ext.define('Ext.draw.Draw', {
34484     
34485
34486     singleton: true,
34487
34488     requires: ['Ext.draw.Color'],
34489
34490     
34491
34492     pathToStringRE: /,?([achlmqrstvxz]),?/gi,
34493     pathCommandRE: /([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig,
34494     pathValuesRE: /(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig,
34495     stopsRE: /^(\d+%?)$/,
34496     radian: Math.PI / 180,
34497
34498     availableAnimAttrs: {
34499         along: "along",
34500         blur: null,
34501         "clip-rect": "csv",
34502         cx: null,
34503         cy: null,
34504         fill: "color",
34505         "fill-opacity": null,
34506         "font-size": null,
34507         height: null,
34508         opacity: null,
34509         path: "path",
34510         r: null,
34511         rotation: "csv",
34512         rx: null,
34513         ry: null,
34514         scale: "csv",
34515         stroke: "color",
34516         "stroke-opacity": null,
34517         "stroke-width": null,
34518         translation: "csv",
34519         width: null,
34520         x: null,
34521         y: null
34522     },
34523
34524     is: function(o, type) {
34525         type = String(type).toLowerCase();
34526         return (type == "object" && o === Object(o)) ||
34527             (type == "undefined" && typeof o == type) ||
34528             (type == "null" && o === null) ||
34529             (type == "array" && Array.isArray && Array.isArray(o)) ||
34530             (Object.prototype.toString.call(o).toLowerCase().slice(8, -1)) == type;
34531     },
34532
34533     ellipsePath: function(sprite) {
34534         var attr = sprite.attr;
34535         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);
34536     },
34537
34538     rectPath: function(sprite) {
34539         var attr = sprite.attr;
34540         if (attr.radius) {
34541             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);
34542         }
34543         else {
34544             return Ext.String.format("M{0},{1}l{2},0,0,{3},{4},0z", attr.x, attr.y, attr.width, attr.height, -attr.width);
34545         }
34546     },
34547
34548     
34549     path2string: function () {
34550         return this.join(",").replace(Ext.draw.Draw.pathToStringRE, "$1");
34551     },
34552
34553     
34554     pathToString: function(arrayPath) {
34555         return arrayPath.join(",").replace(Ext.draw.Draw.pathToStringRE, "$1");
34556     },
34557
34558     parsePathString: function (pathString) {
34559         if (!pathString) {
34560             return null;
34561         }
34562         var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0},
34563             data = [],
34564             me = this;
34565         if (me.is(pathString, "array") && me.is(pathString[0], "array")) { 
34566             data = me.pathClone(pathString);
34567         }
34568         if (!data.length) {
34569             String(pathString).replace(me.pathCommandRE, function (a, b, c) {
34570                 var params = [],
34571                     name = b.toLowerCase();
34572                 c.replace(me.pathValuesRE, function (a, b) {
34573                     b && params.push(+b);
34574                 });
34575                 if (name == "m" && params.length > 2) {
34576                     data.push([b].concat(Ext.Array.splice(params, 0, 2)));
34577                     name = "l";
34578                     b = (b == "m") ? "l" : "L";
34579                 }
34580                 while (params.length >= paramCounts[name]) {
34581                     data.push([b].concat(Ext.Array.splice(params, 0, paramCounts[name])));
34582                     if (!paramCounts[name]) {
34583                         break;
34584                     }
34585                 }
34586             });
34587         }
34588         data.toString = me.path2string;
34589         return data;
34590     },
34591
34592     mapPath: function (path, matrix) {
34593         if (!matrix) {
34594             return path;
34595         }
34596         var x, y, i, ii, j, jj, pathi;
34597         path = this.path2curve(path);
34598         for (i = 0, ii = path.length; i < ii; i++) {
34599             pathi = path[i];
34600             for (j = 1, jj = pathi.length; j < jj-1; j += 2) {
34601                 x = matrix.x(pathi[j], pathi[j + 1]);
34602                 y = matrix.y(pathi[j], pathi[j + 1]);
34603                 pathi[j] = x;
34604                 pathi[j + 1] = y;
34605             }
34606         }
34607         return path;
34608     },
34609
34610     pathClone: function(pathArray) {
34611         var res = [],
34612             j, jj, i, ii;
34613         if (!this.is(pathArray, "array") || !this.is(pathArray && pathArray[0], "array")) { 
34614             pathArray = this.parsePathString(pathArray);
34615         }
34616         for (i = 0, ii = pathArray.length; i < ii; i++) {
34617             res[i] = [];
34618             for (j = 0, jj = pathArray[i].length; j < jj; j++) {
34619                 res[i][j] = pathArray[i][j];
34620             }
34621         }
34622         res.toString = this.path2string;
34623         return res;
34624     },
34625
34626     pathToAbsolute: function (pathArray) {
34627         if (!this.is(pathArray, "array") || !this.is(pathArray && pathArray[0], "array")) { 
34628             pathArray = this.parsePathString(pathArray);
34629         }
34630         var res = [],
34631             x = 0,
34632             y = 0,
34633             mx = 0,
34634             my = 0,
34635             i = 0,
34636             ln = pathArray.length,
34637             r, pathSegment, j, ln2;
34638         
34639         if (ln && pathArray[0][0] == "M") {
34640             x = +pathArray[0][1];
34641             y = +pathArray[0][2];
34642             mx = x;
34643             my = y;
34644             i++;
34645             res[0] = ["M", x, y];
34646         }
34647         for (; i < ln; i++) {
34648             r = res[i] = [];
34649             pathSegment = pathArray[i];
34650             if (pathSegment[0] != pathSegment[0].toUpperCase()) {
34651                 r[0] = pathSegment[0].toUpperCase();
34652                 switch (r[0]) {
34653                     
34654                     case "A":
34655                         r[1] = pathSegment[1];
34656                         r[2] = pathSegment[2];
34657                         r[3] = pathSegment[3];
34658                         r[4] = pathSegment[4];
34659                         r[5] = pathSegment[5];
34660                         r[6] = +(pathSegment[6] + x);
34661                         r[7] = +(pathSegment[7] + y);
34662                         break;
34663                     
34664                     case "V":
34665                         r[1] = +pathSegment[1] + y;
34666                         break;
34667                     
34668                     case "H":
34669                         r[1] = +pathSegment[1] + x;
34670                         break;
34671                     case "M":
34672                     
34673                         mx = +pathSegment[1] + x;
34674                         my = +pathSegment[2] + y;
34675                     default:
34676                         j = 1;
34677                         ln2 = pathSegment.length;
34678                         for (; j < ln2; j++) {
34679                             r[j] = +pathSegment[j] + ((j % 2) ? x : y);
34680                         }
34681                 }
34682             }
34683             else {
34684                 j = 0;
34685                 ln2 = pathSegment.length;
34686                 for (; j < ln2; j++) {
34687                     res[i][j] = pathSegment[j];
34688                 }
34689             }
34690             switch (r[0]) {
34691                 
34692                 case "Z":
34693                     x = mx;
34694                     y = my;
34695                     break;
34696                 
34697                 case "H":
34698                     x = r[1];
34699                     break;
34700                 
34701                 case "V":
34702                     y = r[1];
34703                     break;
34704                 
34705                 case "M":
34706                     pathSegment = res[i];
34707                     ln2 = pathSegment.length;
34708                     mx = pathSegment[ln2 - 2];
34709                     my = pathSegment[ln2 - 1];
34710                 default:
34711                     pathSegment = res[i];
34712                     ln2 = pathSegment.length;
34713                     x = pathSegment[ln2 - 2];
34714                     y = pathSegment[ln2 - 1];
34715             }
34716         }
34717         res.toString = this.path2string;
34718         return res;
34719     },
34720
34721     
34722     pathToRelative: function (pathArray) {
34723         if (!this.is(pathArray, "array") || !this.is(pathArray && pathArray[0], "array")) {
34724             pathArray = this.parsePathString(pathArray);
34725         }
34726         var res = [],
34727             x = 0,
34728             y = 0,
34729             mx = 0,
34730             my = 0,
34731             start = 0;
34732         if (pathArray[0][0] == "M") {
34733             x = pathArray[0][1];
34734             y = pathArray[0][2];
34735             mx = x;
34736             my = y;
34737             start++;
34738             res.push(["M", x, y]);
34739         }
34740         for (var i = start, ii = pathArray.length; i < ii; i++) {
34741             var r = res[i] = [],
34742                 pa = pathArray[i];
34743             if (pa[0] != pa[0].toLowerCase()) {
34744                 r[0] = pa[0].toLowerCase();
34745                 switch (r[0]) {
34746                     case "a":
34747                         r[1] = pa[1];
34748                         r[2] = pa[2];
34749                         r[3] = pa[3];
34750                         r[4] = pa[4];
34751                         r[5] = pa[5];
34752                         r[6] = +(pa[6] - x).toFixed(3);
34753                         r[7] = +(pa[7] - y).toFixed(3);
34754                         break;
34755                     case "v":
34756                         r[1] = +(pa[1] - y).toFixed(3);
34757                         break;
34758                     case "m":
34759                         mx = pa[1];
34760                         my = pa[2];
34761                     default:
34762                         for (var j = 1, jj = pa.length; j < jj; j++) {
34763                             r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3);
34764                         }
34765                 }
34766             } else {
34767                 r = res[i] = [];
34768                 if (pa[0] == "m") {
34769                     mx = pa[1] + x;
34770                     my = pa[2] + y;
34771                 }
34772                 for (var k = 0, kk = pa.length; k < kk; k++) {
34773                     res[i][k] = pa[k];
34774                 }
34775             }
34776             var len = res[i].length;
34777             switch (res[i][0]) {
34778                 case "z":
34779                     x = mx;
34780                     y = my;
34781                     break;
34782                 case "h":
34783                     x += +res[i][len - 1];
34784                     break;
34785                 case "v":
34786                     y += +res[i][len - 1];
34787                     break;
34788                 default:
34789                     x += +res[i][len - 2];
34790                     y += +res[i][len - 1];
34791             }
34792         }
34793         res.toString = this.path2string;
34794         return res;
34795     },
34796
34797     
34798     path2curve: function (path) {
34799         var me = this,
34800             points = me.pathToAbsolute(path),
34801             ln = points.length,
34802             attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
34803             i, seg, segLn, point;
34804             
34805         for (i = 0; i < ln; i++) {
34806             points[i] = me.command2curve(points[i], attrs);
34807             if (points[i].length > 7) {
34808                     points[i].shift();
34809                     point = points[i];
34810                     while (point.length) {
34811                         Ext.Array.splice(points, i++, 0, ["C"].concat(Ext.Array.splice(point, 0, 6)));
34812                     }
34813                     Ext.Array.erase(points, i, 1);
34814                     ln = points.length;
34815                 }
34816             seg = points[i];
34817             segLn = seg.length;
34818             attrs.x = seg[segLn - 2];
34819             attrs.y = seg[segLn - 1];
34820             attrs.bx = parseFloat(seg[segLn - 4]) || attrs.x;
34821             attrs.by = parseFloat(seg[segLn - 3]) || attrs.y;
34822         }
34823         return points;
34824     },
34825     
34826     interpolatePaths: function (path, path2) {
34827         var me = this,
34828             p = me.pathToAbsolute(path),
34829             p2 = me.pathToAbsolute(path2),
34830             attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
34831             attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
34832             fixArc = function (pp, i) {
34833                 if (pp[i].length > 7) {
34834                     pp[i].shift();
34835                     var pi = pp[i];
34836                     while (pi.length) {
34837                         Ext.Array.splice(pp, i++, 0, ["C"].concat(Ext.Array.splice(pi, 0, 6)));
34838                     }
34839                     Ext.Array.erase(pp, i, 1);
34840                     ii = Math.max(p.length, p2.length || 0);
34841                 }
34842             },
34843             fixM = function (path1, path2, a1, a2, i) {
34844                 if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") {
34845                     Ext.Array.splice(path2, i, 0, ["M", a2.x, a2.y]);
34846                     a1.bx = 0;
34847                     a1.by = 0;
34848                     a1.x = path1[i][1];
34849                     a1.y = path1[i][2];
34850                     ii = Math.max(p.length, p2.length || 0);
34851                 }
34852             };
34853         for (var i = 0, ii = Math.max(p.length, p2.length || 0); i < ii; i++) {
34854             p[i] = me.command2curve(p[i], attrs);
34855             fixArc(p, i);
34856             (p2[i] = me.command2curve(p2[i], attrs2));
34857             fixArc(p2, i);
34858             fixM(p, p2, attrs, attrs2, i);
34859             fixM(p2, p, attrs2, attrs, i);
34860             var seg = p[i],
34861                 seg2 = p2[i],
34862                 seglen = seg.length,
34863                 seg2len = seg2.length;
34864             attrs.x = seg[seglen - 2];
34865             attrs.y = seg[seglen - 1];
34866             attrs.bx = parseFloat(seg[seglen - 4]) || attrs.x;
34867             attrs.by = parseFloat(seg[seglen - 3]) || attrs.y;
34868             attrs2.bx = (parseFloat(seg2[seg2len - 4]) || attrs2.x);
34869             attrs2.by = (parseFloat(seg2[seg2len - 3]) || attrs2.y);
34870             attrs2.x = seg2[seg2len - 2];
34871             attrs2.y = seg2[seg2len - 1];
34872         }
34873         return [p, p2];
34874     },
34875     
34876     
34877     command2curve: function (pathCommand, d) {
34878         var me = this;
34879         if (!pathCommand) {
34880             return ["C", d.x, d.y, d.x, d.y, d.x, d.y];
34881         }
34882         if (pathCommand[0] != "T" && pathCommand[0] != "Q") {
34883             d.qx = d.qy = null;
34884         }
34885         switch (pathCommand[0]) {
34886             case "M":
34887                 d.X = pathCommand[1];
34888                 d.Y = pathCommand[2];
34889                 break;
34890             case "A":
34891                 pathCommand = ["C"].concat(me.arc2curve.apply(me, [d.x, d.y].concat(pathCommand.slice(1))));
34892                 break;
34893             case "S":
34894                 pathCommand = ["C", d.x + (d.x - (d.bx || d.x)), d.y + (d.y - (d.by || d.y))].concat(pathCommand.slice(1));
34895                 break;
34896             case "T":
34897                 d.qx = d.x + (d.x - (d.qx || d.x));
34898                 d.qy = d.y + (d.y - (d.qy || d.y));
34899                 pathCommand = ["C"].concat(me.quadratic2curve(d.x, d.y, d.qx, d.qy, pathCommand[1], pathCommand[2]));
34900                 break;
34901             case "Q":
34902                 d.qx = pathCommand[1];
34903                 d.qy = pathCommand[2];
34904                 pathCommand = ["C"].concat(me.quadratic2curve(d.x, d.y, pathCommand[1], pathCommand[2], pathCommand[3], pathCommand[4]));
34905                 break;
34906             case "L":
34907                 pathCommand = ["C"].concat(d.x, d.y, pathCommand[1], pathCommand[2], pathCommand[1], pathCommand[2]);
34908                 break;
34909             case "H":
34910                 pathCommand = ["C"].concat(d.x, d.y, pathCommand[1], d.y, pathCommand[1], d.y);
34911                 break;
34912             case "V":
34913                 pathCommand = ["C"].concat(d.x, d.y, d.x, pathCommand[1], d.x, pathCommand[1]);
34914                 break;
34915             case "Z":
34916                 pathCommand = ["C"].concat(d.x, d.y, d.X, d.Y, d.X, d.Y);
34917                 break;
34918         }
34919         return pathCommand;
34920     },
34921
34922     quadratic2curve: function (x1, y1, ax, ay, x2, y2) {
34923         var _13 = 1 / 3,
34924             _23 = 2 / 3;
34925         return [
34926                 _13 * x1 + _23 * ax,
34927                 _13 * y1 + _23 * ay,
34928                 _13 * x2 + _23 * ax,
34929                 _13 * y2 + _23 * ay,
34930                 x2,
34931                 y2
34932             ];
34933     },
34934     
34935     rotate: function (x, y, rad) {
34936         var cos = Math.cos(rad),
34937             sin = Math.sin(rad),
34938             X = x * cos - y * sin,
34939             Y = x * sin + y * cos;
34940         return {x: X, y: Y};
34941     },
34942
34943     arc2curve: function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {
34944         
34945         
34946         var me = this,
34947             PI = Math.PI,
34948             radian = me.radian,
34949             _120 = PI * 120 / 180,
34950             rad = radian * (+angle || 0),
34951             res = [],
34952             math = Math,
34953             mcos = math.cos,
34954             msin = math.sin,
34955             msqrt = math.sqrt,
34956             mabs = math.abs,
34957             masin = math.asin,
34958             xy, cos, sin, x, y, h, rx2, ry2, k, cx, cy, f1, f2, df, c1, s1, c2, s2,
34959             t, hx, hy, m1, m2, m3, m4, newres, i, ln, f2old, x2old, y2old;
34960         if (!recursive) {
34961             xy = me.rotate(x1, y1, -rad);
34962             x1 = xy.x;
34963             y1 = xy.y;
34964             xy = me.rotate(x2, y2, -rad);
34965             x2 = xy.x;
34966             y2 = xy.y;
34967             cos = mcos(radian * angle);
34968             sin = msin(radian * angle);
34969             x = (x1 - x2) / 2;
34970             y = (y1 - y2) / 2;
34971             h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
34972             if (h > 1) {
34973                 h = msqrt(h);
34974                 rx = h * rx;
34975                 ry = h * ry;
34976             }
34977             rx2 = rx * rx;
34978             ry2 = ry * ry;
34979             k = (large_arc_flag == sweep_flag ? -1 : 1) *
34980                     msqrt(mabs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x)));
34981             cx = k * rx * y / ry + (x1 + x2) / 2;
34982             cy = k * -ry * x / rx + (y1 + y2) / 2;
34983             f1 = masin(((y1 - cy) / ry).toFixed(7));
34984             f2 = masin(((y2 - cy) / ry).toFixed(7));
34985
34986             f1 = x1 < cx ? PI - f1 : f1;
34987             f2 = x2 < cx ? PI - f2 : f2;
34988             if (f1 < 0) {
34989                 f1 = PI * 2 + f1;
34990             }
34991             if (f2 < 0) {
34992                 f2 = PI * 2 + f2;
34993             }
34994             if (sweep_flag && f1 > f2) {
34995                 f1 = f1 - PI * 2;
34996             }
34997             if (!sweep_flag && f2 > f1) {
34998                 f2 = f2 - PI * 2;
34999             }
35000         }
35001         else {
35002             f1 = recursive[0];
35003             f2 = recursive[1];
35004             cx = recursive[2];
35005             cy = recursive[3];
35006         }
35007         df = f2 - f1;
35008         if (mabs(df) > _120) {
35009             f2old = f2;
35010             x2old = x2;
35011             y2old = y2;
35012             f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
35013             x2 = cx + rx * mcos(f2);
35014             y2 = cy + ry * msin(f2);
35015             res = me.arc2curve(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);
35016         }
35017         df = f2 - f1;
35018         c1 = mcos(f1);
35019         s1 = msin(f1);
35020         c2 = mcos(f2);
35021         s2 = msin(f2);
35022         t = math.tan(df / 4);
35023         hx = 4 / 3 * rx * t;
35024         hy = 4 / 3 * ry * t;
35025         m1 = [x1, y1];
35026         m2 = [x1 + hx * s1, y1 - hy * c1];
35027         m3 = [x2 + hx * s2, y2 - hy * c2];
35028         m4 = [x2, y2];
35029         m2[0] = 2 * m1[0] - m2[0];
35030         m2[1] = 2 * m1[1] - m2[1];
35031         if (recursive) {
35032             return [m2, m3, m4].concat(res);
35033         }
35034         else {
35035             res = [m2, m3, m4].concat(res).join().split(",");
35036             newres = [];
35037             ln = res.length;
35038             for (i = 0;  i < ln; i++) {
35039                 newres[i] = i % 2 ? me.rotate(res[i - 1], res[i], rad).y : me.rotate(res[i], res[i + 1], rad).x;
35040             }
35041             return newres;
35042         }
35043     },
35044
35045     
35046     rotateAndTranslatePath: function (sprite) {
35047         var alpha = sprite.rotation.degrees,
35048             cx = sprite.rotation.x,
35049             cy = sprite.rotation.y,
35050             dx = sprite.translation.x,
35051             dy = sprite.translation.y,
35052             path,
35053             i,
35054             p,
35055             xy,
35056             j,
35057             res = [];
35058         if (!alpha && !dx && !dy) {
35059             return this.pathToAbsolute(sprite.attr.path);
35060         }
35061         dx = dx || 0;
35062         dy = dy || 0;
35063         path = this.pathToAbsolute(sprite.attr.path);
35064         for (i = path.length; i--;) {
35065             p = res[i] = path[i].slice();
35066             if (p[0] == "A") {
35067                 xy = this.rotatePoint(p[6], p[7], alpha, cx, cy);
35068                 p[6] = xy.x + dx;
35069                 p[7] = xy.y + dy;
35070             } else {
35071                 j = 1;
35072                 while (p[j + 1] != null) {
35073                     xy = this.rotatePoint(p[j], p[j + 1], alpha, cx, cy);
35074                     p[j] = xy.x + dx;
35075                     p[j + 1] = xy.y + dy;
35076                     j += 2;
35077                 }
35078             }
35079         }
35080         return res;
35081     },
35082
35083     
35084     rotatePoint: function (x, y, alpha, cx, cy) {
35085         if (!alpha) {
35086             return {
35087                 x: x,
35088                 y: y
35089             };
35090         }
35091         cx = cx || 0;
35092         cy = cy || 0;
35093         x = x - cx;
35094         y = y - cy;
35095         alpha = alpha * this.radian;
35096         var cos = Math.cos(alpha),
35097             sin = Math.sin(alpha);
35098         return {
35099             x: x * cos - y * sin + cx,
35100             y: x * sin + y * cos + cy
35101         };
35102     },
35103
35104     pathDimensions: function (path) {
35105         if (!path || !(path + "")) {
35106             return {x: 0, y: 0, width: 0, height: 0};
35107         }
35108         path = this.path2curve(path);
35109         var x = 0, 
35110             y = 0,
35111             X = [],
35112             Y = [],
35113             i = 0,
35114             ln = path.length,
35115             p, xmin, ymin, dim;
35116         for (; i < ln; i++) {
35117             p = path[i];
35118             if (p[0] == "M") {
35119                 x = p[1];
35120                 y = p[2];
35121                 X.push(x);
35122                 Y.push(y);
35123             }
35124             else {
35125                 dim = this.curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
35126                 X = X.concat(dim.min.x, dim.max.x);
35127                 Y = Y.concat(dim.min.y, dim.max.y);
35128                 x = p[5];
35129                 y = p[6];
35130             }
35131         }
35132         xmin = Math.min.apply(0, X);
35133         ymin = Math.min.apply(0, Y);
35134         return {
35135             x: xmin,
35136             y: ymin,
35137             path: path,
35138             width: Math.max.apply(0, X) - xmin,
35139             height: Math.max.apply(0, Y) - ymin
35140         };
35141     },
35142
35143     intersectInside: function(path, cp1, cp2) {
35144         return (cp2[0] - cp1[0]) * (path[1] - cp1[1]) > (cp2[1] - cp1[1]) * (path[0] - cp1[0]);
35145     },
35146
35147     intersectIntersection: function(s, e, cp1, cp2) {
35148         var p = [],
35149             dcx = cp1[0] - cp2[0],
35150             dcy = cp1[1] - cp2[1],
35151             dpx = s[0] - e[0],
35152             dpy = s[1] - e[1],
35153             n1 = cp1[0] * cp2[1] - cp1[1] * cp2[0],
35154             n2 = s[0] * e[1] - s[1] * e[0],
35155             n3 = 1 / (dcx * dpy - dcy * dpx);
35156
35157         p[0] = (n1 * dpx - n2 * dcx) * n3;
35158         p[1] = (n1 * dpy - n2 * dcy) * n3;
35159         return p;
35160     },
35161
35162     intersect: function(subjectPolygon, clipPolygon) {
35163         var me = this,
35164             i = 0,
35165             ln = clipPolygon.length,
35166             cp1 = clipPolygon[ln - 1],
35167             outputList = subjectPolygon,
35168             cp2, s, e, point, ln2, inputList, j;
35169         for (; i < ln; ++i) {
35170             cp2 = clipPolygon[i];
35171             inputList = outputList;
35172             outputList = [];
35173             s = inputList[inputList.length - 1];
35174             j = 0;
35175             ln2 = inputList.length;
35176             for (; j < ln2; j++) {
35177                 e = inputList[j];
35178                 if (me.intersectInside(e, cp1, cp2)) {
35179                     if (!me.intersectInside(s, cp1, cp2)) {
35180                         outputList.push(me.intersectIntersection(s, e, cp1, cp2));
35181                     }
35182                     outputList.push(e);
35183                 }
35184                 else if (me.intersectInside(s, cp1, cp2)) {
35185                     outputList.push(me.intersectIntersection(s, e, cp1, cp2));
35186                 }
35187                 s = e;
35188             }
35189             cp1 = cp2;
35190         }
35191         return outputList;
35192     },
35193
35194     curveDim: function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
35195         var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),
35196             b = 2 * (c1x - p1x) - 2 * (c2x - c1x),
35197             c = p1x - c1x,
35198             t1 = (-b + Math.sqrt(b * b - 4 * a * c)) / 2 / a,
35199             t2 = (-b - Math.sqrt(b * b - 4 * a * c)) / 2 / a,
35200             y = [p1y, p2y],
35201             x = [p1x, p2x],
35202             dot;
35203         if (Math.abs(t1) > 1e12) {
35204             t1 = 0.5;
35205         }
35206         if (Math.abs(t2) > 1e12) {
35207             t2 = 0.5;
35208         }
35209         if (t1 > 0 && t1 < 1) {
35210             dot = this.findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
35211             x.push(dot.x);
35212             y.push(dot.y);
35213         }
35214         if (t2 > 0 && t2 < 1) {
35215             dot = this.findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
35216             x.push(dot.x);
35217             y.push(dot.y);
35218         }
35219         a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y);
35220         b = 2 * (c1y - p1y) - 2 * (c2y - c1y);
35221         c = p1y - c1y;
35222         t1 = (-b + Math.sqrt(b * b - 4 * a * c)) / 2 / a;
35223         t2 = (-b - Math.sqrt(b * b - 4 * a * c)) / 2 / a;
35224         if (Math.abs(t1) > 1e12) {
35225             t1 = 0.5;
35226         }
35227         if (Math.abs(t2) > 1e12) {
35228             t2 = 0.5;
35229         }
35230         if (t1 > 0 && t1 < 1) {
35231             dot = this.findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
35232             x.push(dot.x);
35233             y.push(dot.y);
35234         }
35235         if (t2 > 0 && t2 < 1) {
35236             dot = this.findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
35237             x.push(dot.x);
35238             y.push(dot.y);
35239         }
35240         return {
35241             min: {x: Math.min.apply(0, x), y: Math.min.apply(0, y)},
35242             max: {x: Math.max.apply(0, x), y: Math.max.apply(0, y)}
35243         };
35244     },
35245
35246     
35247     getAnchors: function (prevX, prevY, curX, curY, nextX, nextY, value) {
35248         value = value || 4;
35249         var M = Math,
35250             PI = M.PI,
35251             halfPI = PI / 2,
35252             abs = M.abs,
35253             sin = M.sin,
35254             cos = M.cos,
35255             atan = M.atan,
35256             control1Length, control2Length, control1Angle, control2Angle,
35257             control1X, control1Y, control2X, control2Y, alpha;
35258
35259         
35260         
35261         control1Length = (curX - prevX) / value;
35262         control2Length = (nextX - curX) / value;
35263
35264         
35265         
35266         
35267         
35268         if ((curY >= prevY && curY >= nextY) || (curY <= prevY && curY <= nextY)) {
35269             control1Angle = control2Angle = halfPI;
35270         } else {
35271             control1Angle = atan((curX - prevX) / abs(curY - prevY));
35272             if (prevY < curY) {
35273                 control1Angle = PI - control1Angle;
35274             }
35275             control2Angle = atan((nextX - curX) / abs(curY - nextY));
35276             if (nextY < curY) {
35277                 control2Angle = PI - control2Angle;
35278             }
35279         }
35280
35281         
35282         alpha = halfPI - ((control1Angle + control2Angle) % (PI * 2)) / 2;
35283         if (alpha > halfPI) {
35284             alpha -= PI;
35285         }
35286         control1Angle += alpha;
35287         control2Angle += alpha;
35288
35289         
35290         control1X = curX - control1Length * sin(control1Angle);
35291         control1Y = curY + control1Length * cos(control1Angle);
35292         control2X = curX + control2Length * sin(control2Angle);
35293         control2Y = curY + control2Length * cos(control2Angle);
35294
35295         
35296         
35297         
35298         
35299         if ((curY > prevY && control1Y < prevY) || (curY < prevY && control1Y > prevY)) {
35300             control1X += abs(prevY - control1Y) * (control1X - curX) / (control1Y - curY);
35301             control1Y = prevY;
35302         }
35303         if ((curY > nextY && control2Y < nextY) || (curY < nextY && control2Y > nextY)) {
35304             control2X -= abs(nextY - control2Y) * (control2X - curX) / (control2Y - curY);
35305             control2Y = nextY;
35306         }
35307         
35308         return {
35309             x1: control1X,
35310             y1: control1Y,
35311             x2: control2X,
35312             y2: control2Y
35313         };
35314     },
35315
35316     
35317     smooth: function (originalPath, value) {
35318         var path = this.path2curve(originalPath),
35319             newp = [path[0]],
35320             x = path[0][1],
35321             y = path[0][2],
35322             j,
35323             points,
35324             i = 1,
35325             ii = path.length,
35326             beg = 1,
35327             mx = x,
35328             my = y,
35329             cx = 0,
35330             cy = 0;
35331         for (; i < ii; i++) {
35332             var pathi = path[i],
35333                 pathil = pathi.length,
35334                 pathim = path[i - 1],
35335                 pathiml = pathim.length,
35336                 pathip = path[i + 1],
35337                 pathipl = pathip && pathip.length;
35338             if (pathi[0] == "M") {
35339                 mx = pathi[1];
35340                 my = pathi[2];
35341                 j = i + 1;
35342                 while (path[j][0] != "C") {
35343                     j++;
35344                 }
35345                 cx = path[j][5];
35346                 cy = path[j][6];
35347                 newp.push(["M", mx, my]);
35348                 beg = newp.length;
35349                 x = mx;
35350                 y = my;
35351                 continue;
35352             }
35353             if (pathi[pathil - 2] == mx && pathi[pathil - 1] == my && (!pathip || pathip[0] == "M")) {
35354                 var begl = newp[beg].length;
35355                 points = this.getAnchors(pathim[pathiml - 2], pathim[pathiml - 1], mx, my, newp[beg][begl - 2], newp[beg][begl - 1], value);
35356                 newp[beg][1] = points.x2;
35357                 newp[beg][2] = points.y2;
35358             }
35359             else if (!pathip || pathip[0] == "M") {
35360                 points = {
35361                     x1: pathi[pathil - 2],
35362                     y1: pathi[pathil - 1]
35363                 };
35364             } else {
35365                 points = this.getAnchors(pathim[pathiml - 2], pathim[pathiml - 1], pathi[pathil - 2], pathi[pathil - 1], pathip[pathipl - 2], pathip[pathipl - 1], value);
35366             }
35367             newp.push(["C", x, y, points.x1, points.y1, pathi[pathil - 2], pathi[pathil - 1]]);
35368             x = points.x2;
35369             y = points.y2;
35370         }
35371         return newp;
35372     },
35373
35374     findDotAtSegment: function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
35375         var t1 = 1 - t;
35376         return {
35377             x: Math.pow(t1, 3) * p1x + Math.pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + Math.pow(t, 3) * p2x,
35378             y: Math.pow(t1, 3) * p1y + Math.pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + Math.pow(t, 3) * p2y
35379         };
35380     },
35381
35382     
35383     snapEnds: function (from, to, stepsMax) {
35384         if (Ext.isDate(from)) {
35385             return this.snapEndsByDate(from, to, stepsMax);
35386         }
35387         var step = (to - from) / stepsMax,
35388             level = Math.floor(Math.log(step) / Math.LN10) + 1,
35389             m = Math.pow(10, level),
35390             cur,
35391             modulo = Math.round((step % m) * Math.pow(10, 2 - level)),
35392             interval = [[0, 15], [20, 4], [30, 2], [40, 4], [50, 9], [60, 4], [70, 2], [80, 4], [100, 15]],
35393             stepCount = 0,
35394             value,
35395             weight,
35396             i,
35397             topValue,
35398             topWeight = 1e9,
35399             ln = interval.length;
35400         cur = from = Math.floor(from / m) * m;
35401         for (i = 0; i < ln; i++) {
35402             value = interval[i][0];
35403             weight = (value - modulo) < 0 ? 1e6 : (value - modulo) / interval[i][1];
35404             if (weight < topWeight) {
35405                 topValue = value;
35406                 topWeight = weight;
35407             }
35408         }
35409         step = Math.floor(step * Math.pow(10, -level)) * Math.pow(10, level) + topValue * Math.pow(10, level - 2);
35410         while (cur < to) {
35411             cur += step;
35412             stepCount++;
35413         }
35414         to = +cur.toFixed(10);
35415         return {
35416             from: from,
35417             to: to,
35418             power: level,
35419             step: step,
35420             steps: stepCount
35421         };
35422     },
35423
35424     
35425     snapEndsByDate: function (from, to, stepsMax, lockEnds) {
35426         var selectedStep = false, scales = [
35427                 [Ext.Date.MILLI, [1, 2, 3, 5, 10, 20, 30, 50, 100, 200, 300, 500]],
35428                 [Ext.Date.SECOND, [1, 2, 3, 5, 10, 15, 30]],
35429                 [Ext.Date.MINUTE, [1, 2, 3, 5, 10, 20, 30]],
35430                 [Ext.Date.HOUR, [1, 2, 3, 4, 6, 12]],
35431                 [Ext.Date.DAY, [1, 2, 3, 7, 14]],
35432                 [Ext.Date.MONTH, [1, 2, 3, 4, 6]]
35433             ], j, yearDiff;
35434
35435         
35436         Ext.each(scales, function(scale, i) {
35437             for (j = 0; j < scale[1].length; j++) {
35438                 if (to < Ext.Date.add(from, scale[0], scale[1][j] * stepsMax)) {
35439                     selectedStep = [scale[0], scale[1][j]];
35440                     return false;
35441                 }
35442             }
35443         });
35444         if (!selectedStep) {
35445             yearDiff = this.snapEnds(from.getFullYear(), to.getFullYear() + 1, stepsMax, lockEnds);
35446             selectedStep = [Date.YEAR, Math.round(yearDiff.step)];
35447         }
35448         return this.snapEndsByDateAndStep(from, to, selectedStep, lockEnds);
35449     },
35450
35451
35452     
35453     snapEndsByDateAndStep: function(from, to, step, lockEnds) {
35454         var fromStat = [from.getFullYear(), from.getMonth(), from.getDate(),
35455                 from.getHours(), from.getMinutes(), from.getSeconds(), from.getMilliseconds()],
35456             steps = 0, testFrom, testTo;
35457         if (lockEnds) {
35458             testFrom = from;
35459         } else {
35460             switch (step[0]) {
35461                 case Ext.Date.MILLI:
35462                     testFrom = new Date(fromStat[0], fromStat[1], fromStat[2], fromStat[3],
35463                             fromStat[4], fromStat[5], Math.floor(fromStat[6] / step[1]) * step[1]);
35464                     break;
35465                 case Ext.Date.SECOND:
35466                     testFrom = new Date(fromStat[0], fromStat[1], fromStat[2], fromStat[3],
35467                             fromStat[4], Math.floor(fromStat[5] / step[1]) * step[1], 0);
35468                     break;
35469                 case Ext.Date.MINUTE:
35470                     testFrom = new Date(fromStat[0], fromStat[1], fromStat[2], fromStat[3],
35471                             Math.floor(fromStat[4] / step[1]) * step[1], 0, 0);
35472                     break;
35473                 case Ext.Date.HOUR:
35474                     testFrom = new Date(fromStat[0], fromStat[1], fromStat[2],
35475                             Math.floor(fromStat[3] / step[1]) * step[1], 0, 0, 0);
35476                     break;
35477                 case Ext.Date.DAY:
35478                     testFrom = new Date(fromStat[0], fromStat[1],
35479                             Math.floor(fromStat[2] - 1 / step[1]) * step[1] + 1, 0, 0, 0, 0);
35480                     break;
35481                 case Ext.Date.MONTH:
35482                     testFrom = new Date(fromStat[0], Math.floor(fromStat[1] / step[1]) * step[1], 1, 0, 0, 0, 0);
35483                     break;
35484                 default: 
35485                     testFrom = new Date(Math.floor(fromStat[0] / step[1]) * step[1], 0, 1, 0, 0, 0, 0);
35486                     break;
35487             }
35488         }
35489
35490         testTo = testFrom;
35491         
35492         while (testTo < to) {
35493             testTo = Ext.Date.add(testTo, step[0], step[1]);
35494             steps++;
35495         }
35496
35497         if (lockEnds) {
35498             testTo = to;
35499         }
35500         return {
35501             from : +testFrom,
35502             to : +testTo,
35503             step : (testTo - testFrom) / steps,
35504             steps : steps
35505         };
35506     },
35507
35508     sorter: function (a, b) {
35509         return a.offset - b.offset;
35510     },
35511
35512     rad: function(degrees) {
35513         return degrees % 360 * Math.PI / 180;
35514     },
35515
35516     degrees: function(radian) {
35517         return radian * 180 / Math.PI % 360;
35518     },
35519
35520     withinBox: function(x, y, bbox) {
35521         bbox = bbox || {};
35522         return (x >= bbox.x && x <= (bbox.x + bbox.width) && y >= bbox.y && y <= (bbox.y + bbox.height));
35523     },
35524
35525     parseGradient: function(gradient) {
35526         var me = this,
35527             type = gradient.type || 'linear',
35528             angle = gradient.angle || 0,
35529             radian = me.radian,
35530             stops = gradient.stops,
35531             stopsArr = [],
35532             stop,
35533             vector,
35534             max,
35535             stopObj;
35536
35537         if (type == 'linear') {
35538             vector = [0, 0, Math.cos(angle * radian), Math.sin(angle * radian)];
35539             max = 1 / (Math.max(Math.abs(vector[2]), Math.abs(vector[3])) || 1);
35540             vector[2] *= max;
35541             vector[3] *= max;
35542             if (vector[2] < 0) {
35543                 vector[0] = -vector[2];
35544                 vector[2] = 0;
35545             }
35546             if (vector[3] < 0) {
35547                 vector[1] = -vector[3];
35548                 vector[3] = 0;
35549             }
35550         }
35551
35552         for (stop in stops) {
35553             if (stops.hasOwnProperty(stop) && me.stopsRE.test(stop)) {
35554                 stopObj = {
35555                     offset: parseInt(stop, 10),
35556                     color: Ext.draw.Color.toHex(stops[stop].color) || '#ffffff',
35557                     opacity: stops[stop].opacity || 1
35558                 };
35559                 stopsArr.push(stopObj);
35560             }
35561         }
35562         
35563         Ext.Array.sort(stopsArr, me.sorter);
35564         if (type == 'linear') {
35565             return {
35566                 id: gradient.id,
35567                 type: type,
35568                 vector: vector,
35569                 stops: stopsArr
35570             };
35571         }
35572         else {
35573             return {
35574                 id: gradient.id,
35575                 type: type,
35576                 centerX: gradient.centerX,
35577                 centerY: gradient.centerY,
35578                 focalX: gradient.focalX,
35579                 focalY: gradient.focalY,
35580                 radius: gradient.radius,
35581                 vector: vector,
35582                 stops: stopsArr
35583             };
35584         }
35585     }
35586 });
35587
35588
35589
35590 Ext.define('Ext.fx.PropertyHandler', {
35591
35592     
35593
35594     requires: ['Ext.draw.Draw'],
35595
35596     statics: {
35597         defaultHandler: {
35598             pixelDefaultsRE: /width|height|top$|bottom$|left$|right$/i,
35599             unitRE: /^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/,
35600             scrollRE: /^scroll/i,
35601
35602             computeDelta: function(from, end, damper, initial, attr) {
35603                 damper = (typeof damper == 'number') ? damper : 1;
35604                 var unitRE = this.unitRE,
35605                     match = unitRE.exec(from),
35606                     start, units;
35607                 if (match) {
35608                     from = match[1];
35609                     units = match[2];
35610                     if (!this.scrollRE.test(attr) && !units && this.pixelDefaultsRE.test(attr)) {
35611                         units = 'px';
35612                     }
35613                 }
35614                 from = +from || 0;
35615
35616                 match = unitRE.exec(end);
35617                 if (match) {
35618                     end = match[1];
35619                     units = match[2] || units;
35620                 }
35621                 end = +end || 0;
35622                 start = (initial != null) ? initial : from;
35623                 return {
35624                     from: from,
35625                     delta: (end - start) * damper,
35626                     units: units
35627                 };
35628             },
35629
35630             get: function(from, end, damper, initialFrom, attr) {
35631                 var ln = from.length,
35632                     out = [],
35633                     i, initial, res, j, len;
35634                 for (i = 0; i < ln; i++) {
35635                     if (initialFrom) {
35636                         initial = initialFrom[i][1].from;
35637                     }
35638                     if (Ext.isArray(from[i][1]) && Ext.isArray(end)) {
35639                         res = [];
35640                         j = 0;
35641                         len = from[i][1].length;
35642                         for (; j < len; j++) {
35643                             res.push(this.computeDelta(from[i][1][j], end[j], damper, initial, attr));
35644                         }
35645                         out.push([from[i][0], res]);
35646                     }
35647                     else {
35648                         out.push([from[i][0], this.computeDelta(from[i][1], end, damper, initial, attr)]);
35649                     }
35650                 }
35651                 return out;
35652             },
35653
35654             set: function(values, easing) {
35655                 var ln = values.length,
35656                     out = [],
35657                     i, val, res, len, j;
35658                 for (i = 0; i < ln; i++) {
35659                     val  = values[i][1];
35660                     if (Ext.isArray(val)) {
35661                         res = [];
35662                         j = 0;
35663                         len = val.length;
35664                         for (; j < len; j++) {
35665                             res.push(val[j].from + (val[j].delta * easing) + (val[j].units || 0));
35666                         }
35667                         out.push([values[i][0], res]);
35668                     } else {
35669                         out.push([values[i][0], val.from + (val.delta * easing) + (val.units || 0)]);
35670                     }
35671                 }
35672                 return out;
35673             }
35674         },
35675         color: {
35676             rgbRE: /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,
35677             hexRE: /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,
35678             hex3RE: /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i,
35679
35680             parseColor : function(color, damper) {
35681                 damper = (typeof damper == 'number') ? damper : 1;
35682                 var base,
35683                     out = false,
35684                     match;
35685
35686                 Ext.each([this.hexRE, this.rgbRE, this.hex3RE], function(re, idx) {
35687                     base = (idx % 2 == 0) ? 16 : 10;
35688                     match = re.exec(color);
35689                     if (match && match.length == 4) {
35690                         if (idx == 2) {
35691                             match[1] += match[1];
35692                             match[2] += match[2];
35693                             match[3] += match[3];
35694                         }
35695                         out = {
35696                             red: parseInt(match[1], base),
35697                             green: parseInt(match[2], base),
35698                             blue: parseInt(match[3], base)
35699                         };
35700                         return false;
35701                     }
35702                 });
35703                 return out || color;
35704             },
35705
35706             computeDelta: function(from, end, damper, initial) {
35707                 from = this.parseColor(from);
35708                 end = this.parseColor(end, damper);
35709                 var start = initial ? initial : from,
35710                     tfrom = typeof start,
35711                     tend = typeof end;
35712                 
35713                 if (tfrom == 'string' ||  tfrom == 'undefined' 
35714                   || tend == 'string' || tend == 'undefined') {
35715                     return end || start;
35716                 }
35717                 return {
35718                     from:  from,
35719                     delta: {
35720                         red: Math.round((end.red - start.red) * damper),
35721                         green: Math.round((end.green - start.green) * damper),
35722                         blue: Math.round((end.blue - start.blue) * damper)
35723                     }
35724                 };
35725             },
35726
35727             get: function(start, end, damper, initialFrom) {
35728                 var ln = start.length,
35729                     out = [],
35730                     i, initial;
35731                 for (i = 0; i < ln; i++) {
35732                     if (initialFrom) {
35733                         initial = initialFrom[i][1].from;
35734                     }
35735                     out.push([start[i][0], this.computeDelta(start[i][1], end, damper, initial)]);
35736                 }
35737                 return out;
35738             },
35739
35740             set: function(values, easing) {
35741                 var ln = values.length,
35742                     out = [],
35743                     i, val, parsedString, from, delta;
35744                 for (i = 0; i < ln; i++) {
35745                     val = values[i][1];
35746                     if (val) {
35747                         from = val.from;
35748                         delta = val.delta;
35749                         
35750                         val = (typeof val == 'object' && 'red' in val)? 
35751                                 'rgb(' + val.red + ', ' + val.green + ', ' + val.blue + ')' : val;
35752                         val = (typeof val == 'object' && val.length)? val[0] : val;
35753                         if (typeof val == 'undefined') {
35754                             return [];
35755                         }
35756                         parsedString = typeof val == 'string'? val :
35757                             'rgb(' + [
35758                                   (from.red + Math.round(delta.red * easing)) % 256,
35759                                   (from.green + Math.round(delta.green * easing)) % 256,
35760                                   (from.blue + Math.round(delta.blue * easing)) % 256
35761                               ].join(',') + ')';
35762                         out.push([
35763                             values[i][0],
35764                             parsedString
35765                         ]);
35766                     }
35767                 }
35768                 return out;
35769             }
35770         },
35771         object: {
35772             interpolate: function(prop, damper) {
35773                 damper = (typeof damper == 'number') ? damper : 1;
35774                 var out = {},
35775                     p;
35776                 for(p in prop) {
35777                     out[p] = parseInt(prop[p], 10) * damper;
35778                 }
35779                 return out;
35780             },
35781
35782             computeDelta: function(from, end, damper, initial) {
35783                 from = this.interpolate(from);
35784                 end = this.interpolate(end, damper);
35785                 var start = initial ? initial : from,
35786                     delta = {},
35787                     p;
35788
35789                 for(p in end) {
35790                     delta[p] = end[p] - start[p];
35791                 }
35792                 return {
35793                     from:  from,
35794                     delta: delta
35795                 };
35796             },
35797
35798             get: function(start, end, damper, initialFrom) {
35799                 var ln = start.length,
35800                     out = [],
35801                     i, initial;
35802                 for (i = 0; i < ln; i++) {
35803                     if (initialFrom) {
35804                         initial = initialFrom[i][1].from;
35805                     }
35806                     out.push([start[i][0], this.computeDelta(start[i][1], end, damper, initial)]);
35807                 }
35808                 return out;
35809             },
35810
35811             set: function(values, easing) {
35812                 var ln = values.length,
35813                     out = [],
35814                     outObject = {},
35815                     i, from, delta, val, p;
35816                 for (i = 0; i < ln; i++) {
35817                     val  = values[i][1];
35818                     from = val.from;
35819                     delta = val.delta;
35820                     for (p in from) {
35821                         outObject[p] = Math.round(from[p] + delta[p] * easing);
35822                     }
35823                     out.push([
35824                         values[i][0],
35825                         outObject
35826                     ]);
35827                 }
35828                 return out;
35829             }
35830         },
35831
35832         path: {
35833             computeDelta: function(from, end, damper, initial) {
35834                 damper = (typeof damper == 'number') ? damper : 1;
35835                 var start;
35836                 from = +from || 0;
35837                 end = +end || 0;
35838                 start = (initial != null) ? initial : from;
35839                 return {
35840                     from: from,
35841                     delta: (end - start) * damper
35842                 };
35843             },
35844
35845             forcePath: function(path) {
35846                 if (!Ext.isArray(path) && !Ext.isArray(path[0])) {
35847                     path = Ext.draw.Draw.parsePathString(path);
35848                 }
35849                 return path;
35850             },
35851
35852             get: function(start, end, damper, initialFrom) {
35853                 var endPath = this.forcePath(end),
35854                     out = [],
35855                     startLn = start.length,
35856                     startPathLn, pointsLn, i, deltaPath, initial, j, k, path, startPath;
35857                 for (i = 0; i < startLn; i++) {
35858                     startPath = this.forcePath(start[i][1]);
35859
35860                     deltaPath = Ext.draw.Draw.interpolatePaths(startPath, endPath);
35861                     startPath = deltaPath[0];
35862                     endPath = deltaPath[1];
35863
35864                     startPathLn = startPath.length;
35865                     path = [];
35866                     for (j = 0; j < startPathLn; j++) {
35867                         deltaPath = [startPath[j][0]];
35868                         pointsLn = startPath[j].length;
35869                         for (k = 1; k < pointsLn; k++) {
35870                             initial = initialFrom && initialFrom[0][1][j][k].from;
35871                             deltaPath.push(this.computeDelta(startPath[j][k], endPath[j][k], damper, initial));
35872                         }
35873                         path.push(deltaPath);
35874                     }
35875                     out.push([start[i][0], path]);
35876                 }
35877                 return out;
35878             },
35879
35880             set: function(values, easing) {
35881                 var ln = values.length,
35882                     out = [],
35883                     i, j, k, newPath, calcPath, deltaPath, deltaPathLn, pointsLn;
35884                 for (i = 0; i < ln; i++) {
35885                     deltaPath = values[i][1];
35886                     newPath = [];
35887                     deltaPathLn = deltaPath.length;
35888                     for (j = 0; j < deltaPathLn; j++) {
35889                         calcPath = [deltaPath[j][0]];
35890                         pointsLn = deltaPath[j].length;
35891                         for (k = 1; k < pointsLn; k++) {
35892                             calcPath.push(deltaPath[j][k].from + deltaPath[j][k].delta * easing);
35893                         }
35894                         newPath.push(calcPath.join(','));
35895                     }
35896                     out.push([values[i][0], newPath.join(',')]);
35897                 }
35898                 return out;
35899             }
35900         }
35901         
35902     }
35903 }, function() {
35904     Ext.each([
35905         'outlineColor',
35906         'backgroundColor',
35907         'borderColor',
35908         'borderTopColor',
35909         'borderRightColor', 
35910         'borderBottomColor', 
35911         'borderLeftColor',
35912         'fill',
35913         'stroke'
35914     ], function(prop) {
35915         this[prop] = this.color;
35916     }, this);
35917 });
35918
35919 Ext.define('Ext.fx.Anim', {
35920
35921     
35922
35923     mixins: {
35924         observable: 'Ext.util.Observable'
35925     },
35926
35927     requires: ['Ext.fx.Manager', 'Ext.fx.Animator', 'Ext.fx.Easing', 'Ext.fx.CubicBezier', 'Ext.fx.PropertyHandler'],
35928
35929     
35930
35931     isAnimation: true,
35932
35933     
35934
35935     
35936
35937     
35938     duration: 250,
35939
35940     
35941     delay: 0,
35942
35943     
35944     delayStart: 0,
35945
35946     
35947     dynamic: false,
35948
35949     
35950     easing: 'ease',
35951
35952      
35953
35954     
35955     damper: 1,
35956
35957     
35958     bezierRE: /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,
35959
35960     
35961     reverse: false,
35962
35963     
35964     running: false,
35965
35966     
35967     paused: false,
35968
35969     
35970     iterations: 1,
35971
35972     
35973     alternate: false,
35974
35975     
35976     currentIteration: 0,
35977
35978     
35979     startTime: 0,
35980
35981     
35982
35983     
35984
35985     
35986
35987     
35988
35989     
35990     constructor: function(config) {
35991         var me = this,
35992             curve;
35993             
35994         config = config || {};
35995         
35996         if (config.keyframes) {
35997             return Ext.create('Ext.fx.Animator', config);
35998         }
35999         config = Ext.apply(me, config);
36000         if (me.from === undefined) {
36001             me.from = {};
36002         }
36003         me.propHandlers = {};
36004         me.config = config;
36005         me.target = Ext.fx.Manager.createTarget(me.target);
36006         me.easingFn = Ext.fx.Easing[me.easing];
36007         me.target.dynamic = me.dynamic;
36008
36009         
36010         if (!me.easingFn) {
36011             me.easingFn = String(me.easing).match(me.bezierRE);
36012             if (me.easingFn && me.easingFn.length == 5) {
36013                 curve = me.easingFn;
36014                 me.easingFn = Ext.fx.CubicBezier.cubicBezier(+curve[1], +curve[2], +curve[3], +curve[4]);
36015             }
36016         }
36017         me.id = Ext.id(null, 'ext-anim-');
36018         Ext.fx.Manager.addAnim(me);
36019         me.addEvents(
36020             
36021             'beforeanimate',
36022              
36023             'afteranimate',
36024              
36025             'lastframe'
36026         );
36027         me.mixins.observable.constructor.call(me, config);
36028         if (config.callback) {
36029             me.on('afteranimate', config.callback, config.scope);
36030         }
36031         return me;
36032     },
36033
36034     
36035     setAttr: function(attr, value) {
36036         return Ext.fx.Manager.items.get(this.id).setAttr(this.target, attr, value);
36037     },
36038
36039     
36040     initAttrs: function() {
36041         var me = this,
36042             from = me.from,
36043             to = me.to,
36044             initialFrom = me.initialFrom || {},
36045             out = {},
36046             start, end, propHandler, attr;
36047
36048         for (attr in to) {
36049             if (to.hasOwnProperty(attr)) {
36050                 start = me.target.getAttr(attr, from[attr]);
36051                 end = to[attr];
36052                 
36053                 if (!Ext.fx.PropertyHandler[attr]) {
36054                     if (Ext.isObject(end)) {
36055                         propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler.object;
36056                     } else {
36057                         propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler.defaultHandler;
36058                     }
36059                 }
36060                 
36061                 else {
36062                     propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler[attr];
36063                 }
36064                 out[attr] = propHandler.get(start, end, me.damper, initialFrom[attr], attr);
36065             }
36066         }
36067         me.currentAttrs = out;
36068     },
36069
36070     
36071     start: function(startTime) {
36072         var me = this,
36073             delay = me.delay,
36074             delayStart = me.delayStart,
36075             delayDelta;
36076         if (delay) {
36077             if (!delayStart) {
36078                 me.delayStart = startTime;
36079                 return;
36080             }
36081             else {
36082                 delayDelta = startTime - delayStart;
36083                 if (delayDelta < delay) {
36084                     return;
36085                 }
36086                 else {
36087                     
36088                     startTime = new Date(delayStart.getTime() + delay);
36089                 }
36090             }
36091         }
36092         if (me.fireEvent('beforeanimate', me) !== false) {
36093             me.startTime = startTime;
36094             if (!me.paused && !me.currentAttrs) {
36095                 me.initAttrs();
36096             }
36097             me.running = true;
36098         }
36099     },
36100
36101     
36102     runAnim: function(elapsedTime) {
36103         var me = this,
36104             attrs = me.currentAttrs,
36105             duration = me.duration,
36106             easingFn = me.easingFn,
36107             propHandlers = me.propHandlers,
36108             ret = {},
36109             easing, values, attr, lastFrame;
36110
36111         if (elapsedTime >= duration) {
36112             elapsedTime = duration;
36113             lastFrame = true;
36114         }
36115         if (me.reverse) {
36116             elapsedTime = duration - elapsedTime;
36117         }
36118
36119         for (attr in attrs) {
36120             if (attrs.hasOwnProperty(attr)) {
36121                 values = attrs[attr];
36122                 easing = lastFrame ? 1 : easingFn(elapsedTime / duration);
36123                 ret[attr] = propHandlers[attr].set(values, easing);
36124             }
36125         }
36126         return ret;
36127     },
36128
36129     
36130     lastFrame: function() {
36131         var me = this,
36132             iter = me.iterations,
36133             iterCount = me.currentIteration;
36134
36135         iterCount++;
36136         if (iterCount < iter) {
36137             if (me.alternate) {
36138                 me.reverse = !me.reverse;
36139             }
36140             me.startTime = new Date();
36141             me.currentIteration = iterCount;
36142             
36143             me.paused = false;
36144         }
36145         else {
36146             me.currentIteration = 0;
36147             me.end();
36148             me.fireEvent('lastframe', me, me.startTime);
36149         }
36150     },
36151
36152     
36153     end: function() {
36154         var me = this;
36155         me.startTime = 0;
36156         me.paused = false;
36157         me.running = false;
36158         Ext.fx.Manager.removeAnim(me);
36159         me.fireEvent('afteranimate', me, me.startTime);
36160     }
36161 });
36162
36163 Ext.enableFx = true;
36164
36165
36166
36167
36168
36169 Ext.define('Ext.dd.DragDrop', {
36170     requires: ['Ext.dd.DragDropManager'],
36171
36172     
36173     constructor: function(id, sGroup, config) {
36174         if(id) {
36175             this.init(id, sGroup, config);
36176         }
36177     },
36178
36179     
36180
36181     
36182     id: null,
36183
36184     
36185     config: null,
36186
36187     
36188     dragElId: null,
36189
36190     
36191     handleElId: null,
36192
36193     
36194     invalidHandleTypes: null,
36195
36196     
36197     invalidHandleIds: null,
36198
36199     
36200     invalidHandleClasses: null,
36201
36202     
36203     startPageX: 0,
36204
36205     
36206     startPageY: 0,
36207
36208     
36209     groups: null,
36210
36211     
36212     locked: false,
36213
36214     
36215     lock: function() {
36216         this.locked = true;
36217     },
36218
36219     
36220     moveOnly: false,
36221
36222     
36223     unlock: function() {
36224         this.locked = false;
36225     },
36226
36227     
36228     isTarget: true,
36229
36230     
36231     padding: null,
36232
36233     
36234     _domRef: null,
36235
36236     
36237     __ygDragDrop: true,
36238
36239     
36240     constrainX: false,
36241
36242     
36243     constrainY: false,
36244
36245     
36246     minX: 0,
36247
36248     
36249     maxX: 0,
36250
36251     
36252     minY: 0,
36253
36254     
36255     maxY: 0,
36256
36257     
36258     maintainOffset: false,
36259
36260     
36261     xTicks: null,
36262
36263     
36264     yTicks: null,
36265
36266     
36267     primaryButtonOnly: true,
36268
36269     
36270     available: false,
36271
36272     
36273     hasOuterHandles: false,
36274
36275     
36276     b4StartDrag: function(x, y) { },
36277
36278     
36279     startDrag: function(x, y) {  },
36280
36281     
36282     b4Drag: function(e) { },
36283
36284     
36285     onDrag: function(e) {  },
36286
36287     
36288     onDragEnter: function(e, id) {  },
36289
36290     
36291     b4DragOver: function(e) { },
36292
36293     
36294     onDragOver: function(e, id) {  },
36295
36296     
36297     b4DragOut: function(e) { },
36298
36299     
36300     onDragOut: function(e, id) {  },
36301
36302     
36303     b4DragDrop: function(e) { },
36304
36305     
36306     onDragDrop: function(e, id) {  },
36307
36308     
36309     onInvalidDrop: function(e) {  },
36310
36311     
36312     b4EndDrag: function(e) { },
36313
36314     
36315     endDrag: function(e) {  },
36316
36317     
36318     b4MouseDown: function(e) {  },
36319
36320     
36321     onMouseDown: function(e) {  },
36322
36323     
36324     onMouseUp: function(e) {  },
36325
36326     
36327     onAvailable: function () {
36328     },
36329
36330     
36331     defaultPadding: {
36332         left: 0,
36333         right: 0,
36334         top: 0,
36335         bottom: 0
36336     },
36337
36338     
36339     constrainTo : function(constrainTo, pad, inContent){
36340         if(Ext.isNumber(pad)){
36341             pad = {left: pad, right:pad, top:pad, bottom:pad};
36342         }
36343         pad = pad || this.defaultPadding;
36344         var b = Ext.get(this.getEl()).getBox(),
36345             ce = Ext.get(constrainTo),
36346             s = ce.getScroll(),
36347             c,
36348             cd = ce.dom;
36349         if(cd == document.body){
36350             c = { x: s.left, y: s.top, width: Ext.Element.getViewWidth(), height: Ext.Element.getViewHeight()};
36351         }else{
36352             var xy = ce.getXY();
36353             c = {x : xy[0], y: xy[1], width: cd.clientWidth, height: cd.clientHeight};
36354         }
36355
36356
36357         var topSpace = b.y - c.y,
36358             leftSpace = b.x - c.x;
36359
36360         this.resetConstraints();
36361         this.setXConstraint(leftSpace - (pad.left||0), 
36362                 c.width - leftSpace - b.width - (pad.right||0), 
36363                                 this.xTickSize
36364         );
36365         this.setYConstraint(topSpace - (pad.top||0), 
36366                 c.height - topSpace - b.height - (pad.bottom||0), 
36367                                 this.yTickSize
36368         );
36369     },
36370
36371     
36372     getEl: function() {
36373         if (!this._domRef) {
36374             this._domRef = Ext.getDom(this.id);
36375         }
36376
36377         return this._domRef;
36378     },
36379
36380     
36381     getDragEl: function() {
36382         return Ext.getDom(this.dragElId);
36383     },
36384
36385     
36386     init: function(id, sGroup, config) {
36387         this.initTarget(id, sGroup, config);
36388         Ext.EventManager.on(this.id, "mousedown", this.handleMouseDown, this);
36389         
36390     },
36391
36392     
36393     initTarget: function(id, sGroup, config) {
36394         
36395         this.config = config || {};
36396
36397         
36398         this.DDMInstance = Ext.dd.DragDropManager;
36399         
36400         this.groups = {};
36401
36402         
36403         
36404         if (typeof id !== "string") {
36405             id = Ext.id(id);
36406         }
36407
36408         
36409         this.id = id;
36410
36411         
36412         this.addToGroup((sGroup) ? sGroup : "default");
36413
36414         
36415         
36416         this.handleElId = id;
36417
36418         
36419         this.setDragElId(id);
36420
36421         
36422         this.invalidHandleTypes = { A: "A" };
36423         this.invalidHandleIds = {};
36424         this.invalidHandleClasses = [];
36425
36426         this.applyConfig();
36427
36428         this.handleOnAvailable();
36429     },
36430
36431     
36432     applyConfig: function() {
36433
36434         
36435         
36436         this.padding           = this.config.padding || [0, 0, 0, 0];
36437         this.isTarget          = (this.config.isTarget !== false);
36438         this.maintainOffset    = (this.config.maintainOffset);
36439         this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
36440
36441     },
36442
36443     
36444     handleOnAvailable: function() {
36445         this.available = true;
36446         this.resetConstraints();
36447         this.onAvailable();
36448     },
36449
36450     
36451     setPadding: function(iTop, iRight, iBot, iLeft) {
36452         
36453         if (!iRight && 0 !== iRight) {
36454             this.padding = [iTop, iTop, iTop, iTop];
36455         } else if (!iBot && 0 !== iBot) {
36456             this.padding = [iTop, iRight, iTop, iRight];
36457         } else {
36458             this.padding = [iTop, iRight, iBot, iLeft];
36459         }
36460     },
36461
36462     
36463     setInitPosition: function(diffX, diffY) {
36464         var el = this.getEl();
36465
36466         if (!this.DDMInstance.verifyEl(el)) {
36467             return;
36468         }
36469
36470         var dx = diffX || 0;
36471         var dy = diffY || 0;
36472
36473         var p = Ext.Element.getXY( el );
36474
36475         this.initPageX = p[0] - dx;
36476         this.initPageY = p[1] - dy;
36477
36478         this.lastPageX = p[0];
36479         this.lastPageY = p[1];
36480
36481         this.setStartPosition(p);
36482     },
36483
36484     
36485     setStartPosition: function(pos) {
36486         var p = pos || Ext.Element.getXY( this.getEl() );
36487         this.deltaSetXY = null;
36488
36489         this.startPageX = p[0];
36490         this.startPageY = p[1];
36491     },
36492
36493     
36494     addToGroup: function(sGroup) {
36495         this.groups[sGroup] = true;
36496         this.DDMInstance.regDragDrop(this, sGroup);
36497     },
36498
36499     
36500     removeFromGroup: function(sGroup) {
36501         if (this.groups[sGroup]) {
36502             delete this.groups[sGroup];
36503         }
36504
36505         this.DDMInstance.removeDDFromGroup(this, sGroup);
36506     },
36507
36508     
36509     setDragElId: function(id) {
36510         this.dragElId = id;
36511     },
36512
36513     
36514     setHandleElId: function(id) {
36515         if (typeof id !== "string") {
36516             id = Ext.id(id);
36517         }
36518         this.handleElId = id;
36519         this.DDMInstance.regHandle(this.id, id);
36520     },
36521
36522     
36523     setOuterHandleElId: function(id) {
36524         if (typeof id !== "string") {
36525             id = Ext.id(id);
36526         }
36527         Ext.EventManager.on(id, "mousedown", this.handleMouseDown, this);
36528         this.setHandleElId(id);
36529
36530         this.hasOuterHandles = true;
36531     },
36532
36533     
36534     unreg: function() {
36535         Ext.EventManager.un(this.id, "mousedown", this.handleMouseDown, this);
36536         this._domRef = null;
36537         this.DDMInstance._remove(this);
36538     },
36539
36540     destroy : function(){
36541         this.unreg();
36542     },
36543
36544     
36545     isLocked: function() {
36546         return (this.DDMInstance.isLocked() || this.locked);
36547     },
36548
36549     
36550     handleMouseDown: function(e, oDD){
36551         if (this.primaryButtonOnly && e.button != 0) {
36552             return;
36553         }
36554
36555         if (this.isLocked()) {
36556             return;
36557         }
36558
36559         this.DDMInstance.refreshCache(this.groups);
36560
36561         var pt = e.getPoint();
36562         if (!this.hasOuterHandles && !this.DDMInstance.isOverTarget(pt, this) )  {
36563         } else {
36564             if (this.clickValidator(e)) {
36565                 
36566                 this.setStartPosition();
36567                 this.b4MouseDown(e);
36568                 this.onMouseDown(e);
36569
36570                 this.DDMInstance.handleMouseDown(e, this);
36571
36572                 this.DDMInstance.stopEvent(e);
36573             } else {
36574
36575
36576             }
36577         }
36578     },
36579
36580     clickValidator: function(e) {
36581         var target = e.getTarget();
36582         return ( this.isValidHandleChild(target) &&
36583                     (this.id == this.handleElId ||
36584                         this.DDMInstance.handleWasClicked(target, this.id)) );
36585     },
36586
36587     
36588     addInvalidHandleType: function(tagName) {
36589         var type = tagName.toUpperCase();
36590         this.invalidHandleTypes[type] = type;
36591     },
36592
36593     
36594     addInvalidHandleId: function(id) {
36595         if (typeof id !== "string") {
36596             id = Ext.id(id);
36597         }
36598         this.invalidHandleIds[id] = id;
36599     },
36600
36601     
36602     addInvalidHandleClass: function(cssClass) {
36603         this.invalidHandleClasses.push(cssClass);
36604     },
36605
36606     
36607     removeInvalidHandleType: function(tagName) {
36608         var type = tagName.toUpperCase();
36609         
36610         delete this.invalidHandleTypes[type];
36611     },
36612
36613     
36614     removeInvalidHandleId: function(id) {
36615         if (typeof id !== "string") {
36616             id = Ext.id(id);
36617         }
36618         delete this.invalidHandleIds[id];
36619     },
36620
36621     
36622     removeInvalidHandleClass: function(cssClass) {
36623         for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
36624             if (this.invalidHandleClasses[i] == cssClass) {
36625                 delete this.invalidHandleClasses[i];
36626             }
36627         }
36628     },
36629
36630     
36631     isValidHandleChild: function(node) {
36632
36633         var valid = true;
36634         
36635         var nodeName;
36636         try {
36637             nodeName = node.nodeName.toUpperCase();
36638         } catch(e) {
36639             nodeName = node.nodeName;
36640         }
36641         valid = valid && !this.invalidHandleTypes[nodeName];
36642         valid = valid && !this.invalidHandleIds[node.id];
36643
36644         for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
36645             valid = !Ext.fly(node).hasCls(this.invalidHandleClasses[i]);
36646         }
36647
36648
36649         return valid;
36650
36651     },
36652
36653     
36654     setXTicks: function(iStartX, iTickSize) {
36655         this.xTicks = [];
36656         this.xTickSize = iTickSize;
36657
36658         var tickMap = {};
36659
36660         for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
36661             if (!tickMap[i]) {
36662                 this.xTicks[this.xTicks.length] = i;
36663                 tickMap[i] = true;
36664             }
36665         }
36666
36667         for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
36668             if (!tickMap[i]) {
36669                 this.xTicks[this.xTicks.length] = i;
36670                 tickMap[i] = true;
36671             }
36672         }
36673
36674         Ext.Array.sort(this.xTicks, this.DDMInstance.numericSort);
36675     },
36676
36677     
36678     setYTicks: function(iStartY, iTickSize) {
36679         this.yTicks = [];
36680         this.yTickSize = iTickSize;
36681
36682         var tickMap = {};
36683
36684         for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
36685             if (!tickMap[i]) {
36686                 this.yTicks[this.yTicks.length] = i;
36687                 tickMap[i] = true;
36688             }
36689         }
36690
36691         for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
36692             if (!tickMap[i]) {
36693                 this.yTicks[this.yTicks.length] = i;
36694                 tickMap[i] = true;
36695             }
36696         }
36697
36698         Ext.Array.sort(this.yTicks, this.DDMInstance.numericSort);
36699     },
36700
36701     
36702     setXConstraint: function(iLeft, iRight, iTickSize) {
36703         this.leftConstraint = iLeft;
36704         this.rightConstraint = iRight;
36705
36706         this.minX = this.initPageX - iLeft;
36707         this.maxX = this.initPageX + iRight;
36708         if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
36709
36710         this.constrainX = true;
36711     },
36712
36713     
36714     clearConstraints: function() {
36715         this.constrainX = false;
36716         this.constrainY = false;
36717         this.clearTicks();
36718     },
36719
36720     
36721     clearTicks: function() {
36722         this.xTicks = null;
36723         this.yTicks = null;
36724         this.xTickSize = 0;
36725         this.yTickSize = 0;
36726     },
36727
36728     
36729     setYConstraint: function(iUp, iDown, iTickSize) {
36730         this.topConstraint = iUp;
36731         this.bottomConstraint = iDown;
36732
36733         this.minY = this.initPageY - iUp;
36734         this.maxY = this.initPageY + iDown;
36735         if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
36736
36737         this.constrainY = true;
36738
36739     },
36740
36741     
36742     resetConstraints: function() {
36743         
36744         if (this.initPageX || this.initPageX === 0) {
36745             
36746             var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
36747             var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
36748
36749             this.setInitPosition(dx, dy);
36750
36751         
36752         } else {
36753             this.setInitPosition();
36754         }
36755
36756         if (this.constrainX) {
36757             this.setXConstraint( this.leftConstraint,
36758                                  this.rightConstraint,
36759                                  this.xTickSize        );
36760         }
36761
36762         if (this.constrainY) {
36763             this.setYConstraint( this.topConstraint,
36764                                  this.bottomConstraint,
36765                                  this.yTickSize         );
36766         }
36767     },
36768
36769     
36770     getTick: function(val, tickArray) {
36771         if (!tickArray) {
36772             
36773             
36774             return val;
36775         } else if (tickArray[0] >= val) {
36776             
36777             
36778             return tickArray[0];
36779         } else {
36780             for (var i=0, len=tickArray.length; i<len; ++i) {
36781                 var next = i + 1;
36782                 if (tickArray[next] && tickArray[next] >= val) {
36783                     var diff1 = val - tickArray[i];
36784                     var diff2 = tickArray[next] - val;
36785                     return (diff2 > diff1) ? tickArray[i] : tickArray[next];
36786                 }
36787             }
36788
36789             
36790             
36791             return tickArray[tickArray.length - 1];
36792         }
36793     },
36794
36795     
36796     toString: function() {
36797         return ("DragDrop " + this.id);
36798     }
36799
36800 });
36801
36802
36803
36804
36805
36806 Ext.define('Ext.dd.DD', {
36807     extend: 'Ext.dd.DragDrop',
36808     requires: ['Ext.dd.DragDropManager'],
36809
36810     
36811     constructor: function(id, sGroup, config) {
36812         if (id) {
36813             this.init(id, sGroup, config);
36814         }
36815     },
36816
36817     
36818     scroll: true,
36819
36820     
36821     autoOffset: function(iPageX, iPageY) {
36822         var x = iPageX - this.startPageX;
36823         var y = iPageY - this.startPageY;
36824         this.setDelta(x, y);
36825     },
36826
36827     
36828     setDelta: function(iDeltaX, iDeltaY) {
36829         this.deltaX = iDeltaX;
36830         this.deltaY = iDeltaY;
36831     },
36832
36833     
36834     setDragElPos: function(iPageX, iPageY) {
36835         
36836         
36837
36838         var el = this.getDragEl();
36839         this.alignElWithMouse(el, iPageX, iPageY);
36840     },
36841
36842     
36843     alignElWithMouse: function(el, iPageX, iPageY) {
36844         var oCoord = this.getTargetCoord(iPageX, iPageY),
36845             fly = el.dom ? el : Ext.fly(el, '_dd'),
36846             elSize = fly.getSize(),
36847             EL = Ext.Element,
36848             vpSize;
36849
36850         if (!this.deltaSetXY) {
36851             vpSize = this.cachedViewportSize = { width: EL.getDocumentWidth(), height: EL.getDocumentHeight() };
36852             var aCoord = [
36853                 Math.max(0, Math.min(oCoord.x, vpSize.width - elSize.width)),
36854                 Math.max(0, Math.min(oCoord.y, vpSize.height - elSize.height))
36855             ];
36856             fly.setXY(aCoord);
36857             var newLeft = fly.getLeft(true);
36858             var newTop  = fly.getTop(true);
36859             this.deltaSetXY = [newLeft - oCoord.x, newTop - oCoord.y];
36860         } else {
36861             vpSize = this.cachedViewportSize;
36862             fly.setLeftTop(
36863                 Math.max(0, Math.min(oCoord.x + this.deltaSetXY[0], vpSize.width - elSize.width)),
36864                 Math.max(0, Math.min(oCoord.y + this.deltaSetXY[1], vpSize.height - elSize.height))
36865             );
36866         }
36867
36868         this.cachePosition(oCoord.x, oCoord.y);
36869         this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
36870         return oCoord;
36871     },
36872
36873     
36874     cachePosition: function(iPageX, iPageY) {
36875         if (iPageX) {
36876             this.lastPageX = iPageX;
36877             this.lastPageY = iPageY;
36878         } else {
36879             var aCoord = Ext.Element.getXY(this.getEl());
36880             this.lastPageX = aCoord[0];
36881             this.lastPageY = aCoord[1];
36882         }
36883     },
36884
36885     
36886     autoScroll: function(x, y, h, w) {
36887
36888         if (this.scroll) {
36889             
36890             var clientH = Ext.Element.getViewHeight();
36891
36892             
36893             var clientW = Ext.Element.getViewWidth();
36894
36895             
36896             var st = this.DDMInstance.getScrollTop();
36897
36898             
36899             var sl = this.DDMInstance.getScrollLeft();
36900
36901             
36902             var bot = h + y;
36903
36904             
36905             var right = w + x;
36906
36907             
36908             
36909             
36910             var toBot = (clientH + st - y - this.deltaY);
36911
36912             
36913             var toRight = (clientW + sl - x - this.deltaX);
36914
36915
36916             
36917             
36918             var thresh = 40;
36919
36920             
36921             
36922             
36923             var scrAmt = (document.all) ? 80 : 30;
36924
36925             
36926             
36927             if ( bot > clientH && toBot < thresh ) {
36928                 window.scrollTo(sl, st + scrAmt);
36929             }
36930
36931             
36932             
36933             if ( y < st && st > 0 && y - st < thresh ) {
36934                 window.scrollTo(sl, st - scrAmt);
36935             }
36936
36937             
36938             
36939             if ( right > clientW && toRight < thresh ) {
36940                 window.scrollTo(sl + scrAmt, st);
36941             }
36942
36943             
36944             
36945             if ( x < sl && sl > 0 && x - sl < thresh ) {
36946                 window.scrollTo(sl - scrAmt, st);
36947             }
36948         }
36949     },
36950
36951     
36952     getTargetCoord: function(iPageX, iPageY) {
36953         var x = iPageX - this.deltaX;
36954         var y = iPageY - this.deltaY;
36955
36956         if (this.constrainX) {
36957             if (x < this.minX) {
36958                 x = this.minX;
36959             }
36960             if (x > this.maxX) {
36961                 x = this.maxX;
36962             }
36963         }
36964
36965         if (this.constrainY) {
36966             if (y < this.minY) {
36967                 y = this.minY;
36968             }
36969             if (y > this.maxY) {
36970                 y = this.maxY;
36971             }
36972         }
36973
36974         x = this.getTick(x, this.xTicks);
36975         y = this.getTick(y, this.yTicks);
36976
36977
36978         return {x: x, y: y};
36979     },
36980
36981     
36982     applyConfig: function() {
36983         this.callParent();
36984         this.scroll = (this.config.scroll !== false);
36985     },
36986
36987     
36988     b4MouseDown: function(e) {
36989         
36990         this.autoOffset(e.getPageX(), e.getPageY());
36991     },
36992
36993     
36994     b4Drag: function(e) {
36995         this.setDragElPos(e.getPageX(), e.getPageY());
36996     },
36997
36998     toString: function() {
36999         return ("DD " + this.id);
37000     }
37001
37002     
37003     
37004     
37005     
37006
37007 });
37008
37009
37010
37011
37012 Ext.define('Ext.dd.DDProxy', {
37013     extend: 'Ext.dd.DD',
37014
37015     statics: {
37016         
37017         dragElId: "ygddfdiv"
37018     },
37019
37020     
37021     constructor: function(id, sGroup, config) {
37022         if (id) {
37023             this.init(id, sGroup, config);
37024             this.initFrame();
37025         }
37026     },
37027
37028     
37029     resizeFrame: true,
37030
37031     
37032     centerFrame: false,
37033
37034     
37035     createFrame: function() {
37036         var self = this;
37037         var body = document.body;
37038
37039         if (!body || !body.firstChild) {
37040             setTimeout( function() { self.createFrame(); }, 50 );
37041             return;
37042         }
37043
37044         var div = this.getDragEl();
37045
37046         if (!div) {
37047             div    = document.createElement("div");
37048             div.id = this.dragElId;
37049             var s  = div.style;
37050
37051             s.position   = "absolute";
37052             s.visibility = "hidden";
37053             s.cursor     = "move";
37054             s.border     = "2px solid #aaa";
37055             s.zIndex     = 999;
37056
37057             
37058             
37059             
37060             body.insertBefore(div, body.firstChild);
37061         }
37062     },
37063
37064     
37065     initFrame: function() {
37066         this.createFrame();
37067     },
37068
37069     applyConfig: function() {
37070         this.callParent();
37071
37072         this.resizeFrame = (this.config.resizeFrame !== false);
37073         this.centerFrame = (this.config.centerFrame);
37074         this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
37075     },
37076
37077     
37078     showFrame: function(iPageX, iPageY) {
37079         var el = this.getEl();
37080         var dragEl = this.getDragEl();
37081         var s = dragEl.style;
37082
37083         this._resizeProxy();
37084
37085         if (this.centerFrame) {
37086             this.setDelta( Math.round(parseInt(s.width,  10)/2),
37087                            Math.round(parseInt(s.height, 10)/2) );
37088         }
37089
37090         this.setDragElPos(iPageX, iPageY);
37091
37092         Ext.fly(dragEl).show();
37093     },
37094
37095     
37096     _resizeProxy: function() {
37097         if (this.resizeFrame) {
37098             var el = this.getEl();
37099             Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
37100         }
37101     },
37102
37103     
37104     b4MouseDown: function(e) {
37105         var x = e.getPageX();
37106         var y = e.getPageY();
37107         this.autoOffset(x, y);
37108         this.setDragElPos(x, y);
37109     },
37110
37111     
37112     b4StartDrag: function(x, y) {
37113         
37114         this.showFrame(x, y);
37115     },
37116
37117     
37118     b4EndDrag: function(e) {
37119         Ext.fly(this.getDragEl()).hide();
37120     },
37121
37122     
37123     
37124     
37125     endDrag: function(e) {
37126
37127         var lel = this.getEl();
37128         var del = this.getDragEl();
37129
37130         
37131         del.style.visibility = "";
37132
37133         this.beforeMove();
37134         
37135         
37136         lel.style.visibility = "hidden";
37137         Ext.dd.DDM.moveToEl(lel, del);
37138         del.style.visibility = "hidden";
37139         lel.style.visibility = "";
37140
37141         this.afterDrag();
37142     },
37143
37144     beforeMove : function(){
37145
37146     },
37147
37148     afterDrag : function(){
37149
37150     },
37151
37152     toString: function() {
37153         return ("DDProxy " + this.id);
37154     }
37155
37156 });
37157
37158
37159 Ext.define('Ext.dd.DragSource', {
37160     extend: 'Ext.dd.DDProxy',
37161     requires: [
37162         'Ext.dd.StatusProxy',
37163         'Ext.dd.DragDropManager'
37164     ],
37165
37166     
37167
37168     
37169     dropAllowed : Ext.baseCSSPrefix + 'dd-drop-ok',
37170     
37171     dropNotAllowed : Ext.baseCSSPrefix + 'dd-drop-nodrop',
37172
37173     
37174     animRepair: true,
37175
37176     
37177     repairHighlightColor: 'c3daf9',
37178
37179     
37180     constructor: function(el, config) {
37181         this.el = Ext.get(el);
37182         if(!this.dragData){
37183             this.dragData = {};
37184         }
37185
37186         Ext.apply(this, config);
37187
37188         if(!this.proxy){
37189             this.proxy = Ext.create('Ext.dd.StatusProxy', {
37190                 animRepair: this.animRepair
37191             });
37192         }
37193         this.callParent([this.el.dom, this.ddGroup || this.group,
37194               {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true}]);
37195
37196         this.dragging = false;
37197     },
37198
37199     
37200     getDragData : function(e){
37201         return this.dragData;
37202     },
37203
37204     
37205     onDragEnter : function(e, id){
37206         var target = Ext.dd.DragDropManager.getDDById(id);
37207         this.cachedTarget = target;
37208         if (this.beforeDragEnter(target, e, id) !== false) {
37209             if (target.isNotifyTarget) {
37210                 var status = target.notifyEnter(this, e, this.dragData);
37211                 this.proxy.setStatus(status);
37212             } else {
37213                 this.proxy.setStatus(this.dropAllowed);
37214             }
37215
37216             if (this.afterDragEnter) {
37217                 
37218                 this.afterDragEnter(target, e, id);
37219             }
37220         }
37221     },
37222
37223     
37224     beforeDragEnter: function(target, e, id) {
37225         return true;
37226     },
37227
37228     
37229     alignElWithMouse: function() {
37230         this.callParent(arguments);
37231         this.proxy.sync();
37232     },
37233
37234     
37235     onDragOver: function(e, id) {
37236         var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id);
37237         if (this.beforeDragOver(target, e, id) !== false) {
37238             if(target.isNotifyTarget){
37239                 var status = target.notifyOver(this, e, this.dragData);
37240                 this.proxy.setStatus(status);
37241             }
37242
37243             if (this.afterDragOver) {
37244                 
37245                 this.afterDragOver(target, e, id);
37246             }
37247         }
37248     },
37249
37250     
37251     beforeDragOver: function(target, e, id) {
37252         return true;
37253     },
37254
37255     
37256     onDragOut: function(e, id) {
37257         var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id);
37258         if (this.beforeDragOut(target, e, id) !== false) {
37259             if (target.isNotifyTarget) {
37260                 target.notifyOut(this, e, this.dragData);
37261             }
37262             this.proxy.reset();
37263             if (this.afterDragOut) {
37264                 
37265                 this.afterDragOut(target, e, id);
37266             }
37267         }
37268         this.cachedTarget = null;
37269     },
37270
37271     
37272     beforeDragOut: function(target, e, id){
37273         return true;
37274     },
37275
37276     
37277     onDragDrop: function(e, id){
37278         var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id);
37279         if (this.beforeDragDrop(target, e, id) !== false) {
37280             if (target.isNotifyTarget) {
37281                 if (target.notifyDrop(this, e, this.dragData) !== false) { 
37282                     this.onValidDrop(target, e, id);
37283                 } else {
37284                     this.onInvalidDrop(target, e, id);
37285                 }
37286             } else {
37287                 this.onValidDrop(target, e, id);
37288             }
37289
37290             if (this.afterDragDrop) {
37291                 
37292                 this.afterDragDrop(target, e, id);
37293             }
37294         }
37295         delete this.cachedTarget;
37296     },
37297
37298     
37299     beforeDragDrop: function(target, e, id){
37300         return true;
37301     },
37302
37303     
37304     onValidDrop: function(target, e, id){
37305         this.hideProxy();
37306         if(this.afterValidDrop){
37307             
37308             this.afterValidDrop(target, e, id);
37309         }
37310     },
37311
37312     
37313     getRepairXY: function(e, data){
37314         return this.el.getXY();
37315     },
37316
37317     
37318     onInvalidDrop: function(target, e, id) {
37319         this.beforeInvalidDrop(target, e, id);
37320         if (this.cachedTarget) {
37321             if(this.cachedTarget.isNotifyTarget){
37322                 this.cachedTarget.notifyOut(this, e, this.dragData);
37323             }
37324             this.cacheTarget = null;
37325         }
37326         this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
37327
37328         if (this.afterInvalidDrop) {
37329             
37330             this.afterInvalidDrop(e, id);
37331         }
37332     },
37333
37334     
37335     afterRepair: function() {
37336         var me = this;
37337         if (Ext.enableFx) {
37338             me.el.highlight(me.repairHighlightColor);
37339         }
37340         me.dragging = false;
37341     },
37342
37343     
37344     beforeInvalidDrop: function(target, e, id) {
37345         return true;
37346     },
37347
37348     
37349     handleMouseDown: function(e) {
37350         if (this.dragging) {
37351             return;
37352         }
37353         var data = this.getDragData(e);
37354         if (data && this.onBeforeDrag(data, e) !== false) {
37355             this.dragData = data;
37356             this.proxy.stop();
37357             this.callParent(arguments);
37358         }
37359     },
37360
37361     
37362     onBeforeDrag: function(data, e){
37363         return true;
37364     },
37365
37366     
37367     onStartDrag: Ext.emptyFn,
37368
37369     
37370     startDrag: function(x, y) {
37371         this.proxy.reset();
37372         this.dragging = true;
37373         this.proxy.update("");
37374         this.onInitDrag(x, y);
37375         this.proxy.show();
37376     },
37377
37378     
37379     onInitDrag: function(x, y) {
37380         var clone = this.el.dom.cloneNode(true);
37381         clone.id = Ext.id(); 
37382         this.proxy.update(clone);
37383         this.onStartDrag(x, y);
37384         return true;
37385     },
37386
37387     
37388     getProxy: function() {
37389         return this.proxy;
37390     },
37391
37392     
37393     hideProxy: function() {
37394         this.proxy.hide();
37395         this.proxy.reset(true);
37396         this.dragging = false;
37397     },
37398
37399     
37400     triggerCacheRefresh: function() {
37401         Ext.dd.DDM.refreshCache(this.groups);
37402     },
37403
37404     
37405     b4EndDrag: function(e) {
37406     },
37407
37408     
37409     endDrag : function(e){
37410         this.onEndDrag(this.dragData, e);
37411     },
37412
37413     
37414     onEndDrag : function(data, e){
37415     },
37416
37417     
37418     autoOffset : function(x, y) {
37419         this.setDelta(-12, -20);
37420     },
37421
37422     destroy: function(){
37423         this.callParent();
37424         Ext.destroy(this.proxy);
37425     }
37426 });
37427
37428
37429 Ext.define('Ext.panel.DD', {
37430     extend: 'Ext.dd.DragSource',
37431     requires: ['Ext.panel.Proxy'],
37432
37433     constructor : function(panel, cfg){
37434         this.panel = panel;
37435         this.dragData = {panel: panel};
37436         this.proxy = Ext.create('Ext.panel.Proxy', panel, cfg);
37437
37438         this.callParent([panel.el, cfg]);
37439
37440         Ext.defer(function() {
37441             var header = panel.header,
37442                 el = panel.body;
37443
37444             if(header){
37445                 this.setHandleElId(header.id);
37446                 el = header.el;
37447             }
37448             el.setStyle('cursor', 'move');
37449             this.scroll = false;
37450         }, 200, this);
37451     },
37452
37453     showFrame: Ext.emptyFn,
37454     startDrag: Ext.emptyFn,
37455     b4StartDrag: function(x, y) {
37456         this.proxy.show();
37457     },
37458     b4MouseDown: function(e) {
37459         var x = e.getPageX(),
37460             y = e.getPageY();
37461         this.autoOffset(x, y);
37462     },
37463     onInitDrag : function(x, y){
37464         this.onStartDrag(x, y);
37465         return true;
37466     },
37467     createFrame : Ext.emptyFn,
37468     getDragEl : function(e){
37469         return this.proxy.ghost.el.dom;
37470     },
37471     endDrag : function(e){
37472         this.proxy.hide();
37473         this.panel.saveState();
37474     },
37475
37476     autoOffset : function(x, y) {
37477         x -= this.startPageX;
37478         y -= this.startPageY;
37479         this.setDelta(x, y);
37480     }
37481 });
37482
37483
37484 Ext.define('Ext.layout.component.Dock', {
37485
37486     
37487
37488     alias: ['layout.dock'],
37489
37490     extend: 'Ext.layout.component.AbstractDock'
37491
37492     
37493
37494 });
37495
37496 Ext.define('Ext.panel.Panel', {
37497     extend: 'Ext.panel.AbstractPanel',
37498     requires: [
37499         'Ext.panel.Header',
37500         'Ext.fx.Anim',
37501         'Ext.util.KeyMap',
37502         'Ext.panel.DD',
37503         'Ext.XTemplate',
37504         'Ext.layout.component.Dock',
37505         'Ext.util.Memento'
37506     ],
37507     alias: 'widget.panel',
37508     alternateClassName: 'Ext.Panel',
37509
37510     
37511     collapsedCls: 'collapsed',
37512
37513     
37514     animCollapse: Ext.enableFx,
37515
37516     
37517     minButtonWidth: 75,
37518
37519     
37520     collapsed: false,
37521
37522     
37523     collapseFirst: true,
37524
37525     
37526     hideCollapseTool: false,
37527
37528     
37529     titleCollapse: false,
37530
37531     
37532
37533     
37534
37535     
37536     floatable: true,
37537
37538     
37539
37540     
37541     collapsible: false,
37542
37543     
37544
37545     
37546     closable: false,
37547
37548     
37549     closeAction: 'destroy',
37550
37551     
37552
37553     
37554     preventHeader: false,
37555
37556      
37557     headerPosition: 'top',
37558
37559      
37560     frame: false,
37561
37562     
37563     frameHeader: true,
37564
37565     
37566
37567     
37568
37569     
37570
37571     initComponent: function() {
37572         var me = this,
37573             cls;
37574
37575         me.addEvents(
37576
37577             
37578             'beforeclose',
37579
37580             
37581             "beforeexpand",
37582
37583             
37584             "beforecollapse",
37585
37586             
37587             "expand",
37588
37589             
37590             "collapse",
37591
37592             
37593             'titlechange',
37594
37595             
37596             'iconchange'
37597         );
37598
37599         
37600         this.addStateEvents('expand', 'collapse');
37601
37602         if (me.unstyled) {
37603             me.setUI('plain');
37604         }
37605
37606         if (me.frame) {
37607             me.setUI(me.ui + '-framed');
37608         }
37609
37610         
37611         me.bridgeToolbars();
37612
37613         me.callParent();
37614         me.collapseDirection = me.collapseDirection || me.headerPosition || Ext.Component.DIRECTION_TOP;
37615     },
37616
37617     setBorder: function(border) {
37618         
37619         
37620         
37621         
37622         
37623         
37624         
37625         
37626         
37627         
37628         
37629         
37630         
37631         
37632         
37633
37634         this.callParent(arguments);
37635     },
37636
37637     beforeDestroy: function() {
37638         Ext.destroy(
37639             this.ghostPanel,
37640             this.dd
37641         );
37642         this.callParent();
37643     },
37644
37645     initAria: function() {
37646         this.callParent();
37647         this.initHeaderAria();
37648     },
37649
37650     initHeaderAria: function() {
37651         var me = this,
37652             el = me.el,
37653             header = me.header;
37654         if (el && header) {
37655             el.dom.setAttribute('aria-labelledby', header.titleCmp.id);
37656         }
37657     },
37658
37659     getHeader: function() {
37660         return this.header;
37661     },
37662
37663     
37664     setTitle: function(newTitle) {
37665         var me = this,
37666         oldTitle = this.title;
37667
37668         me.title = newTitle;
37669         if (me.header) {
37670             me.header.setTitle(newTitle);
37671         } else {
37672             me.updateHeader();
37673         }
37674
37675         if (me.reExpander) {
37676             me.reExpander.setTitle(newTitle);
37677         }
37678         me.fireEvent('titlechange', me, newTitle, oldTitle);
37679     },
37680
37681     
37682     setIconCls: function(newIconCls) {
37683         var me = this,
37684             oldIconCls = me.iconCls;
37685
37686         me.iconCls = newIconCls;
37687         var header = me.header;
37688         if (header) {
37689             header.setIconCls(newIconCls);
37690         }
37691         me.fireEvent('iconchange', me, newIconCls, oldIconCls);
37692     },
37693
37694     bridgeToolbars: function() {
37695         var me = this,
37696             docked = [],
37697             fbar,
37698             fbarDefaults,
37699             minButtonWidth = me.minButtonWidth;
37700
37701         function initToolbar (toolbar, pos, useButtonAlign) {
37702             if (Ext.isArray(toolbar)) {
37703                 toolbar = {
37704                     xtype: 'toolbar',
37705                     items: toolbar
37706                 };
37707             }
37708             else if (!toolbar.xtype) {
37709                 toolbar.xtype = 'toolbar';
37710             }
37711             toolbar.dock = pos;
37712             if (pos == 'left' || pos == 'right') {
37713                 toolbar.vertical = true;
37714             }
37715
37716             
37717             if (useButtonAlign) {
37718                 toolbar.layout = Ext.applyIf(toolbar.layout || {}, {
37719                     
37720                     pack: { left:'start', center:'center' }[me.buttonAlign] || 'end'
37721                 });
37722             }
37723             return toolbar;
37724         }
37725
37726         
37727
37728         
37729
37730         
37731         if (me.tbar) {
37732             docked.push(initToolbar(me.tbar, 'top'));
37733             me.tbar = null;
37734         }
37735
37736         
37737         if (me.bbar) {
37738             docked.push(initToolbar(me.bbar, 'bottom'));
37739             me.bbar = null;
37740         }
37741
37742         
37743         if (me.buttons) {
37744             me.fbar = me.buttons;
37745             me.buttons = null;
37746         }
37747
37748         
37749         if (me.fbar) {
37750             fbar = initToolbar(me.fbar, 'bottom', true); 
37751             fbar.ui = 'footer';
37752
37753             
37754             if (minButtonWidth) {
37755                 fbarDefaults = fbar.defaults;
37756                 fbar.defaults = function(config) {
37757                     var defaults = fbarDefaults || {};
37758                     if ((!config.xtype || config.xtype === 'button' || (config.isComponent && config.isXType('button'))) &&
37759                             !('minWidth' in defaults)) {
37760                         defaults = Ext.apply({minWidth: minButtonWidth}, defaults);
37761                     }
37762                     return defaults;
37763                 };
37764             }
37765
37766             docked.push(fbar);
37767             me.fbar = null;
37768         }
37769
37770         
37771         if (me.lbar) {
37772             docked.push(initToolbar(me.lbar, 'left'));
37773             me.lbar = null;
37774         }
37775
37776         
37777         if (me.rbar) {
37778             docked.push(initToolbar(me.rbar, 'right'));
37779             me.rbar = null;
37780         }
37781
37782         if (me.dockedItems) {
37783             if (!Ext.isArray(me.dockedItems)) {
37784                 me.dockedItems = [me.dockedItems];
37785             }
37786             me.dockedItems = me.dockedItems.concat(docked);
37787         } else {
37788             me.dockedItems = docked;
37789         }
37790     },
37791
37792     
37793     initTools: function() {
37794         var me = this;
37795
37796         me.tools = me.tools ? Ext.Array.clone(me.tools) : [];
37797
37798         
37799         
37800         if (me.collapsible && !(me.hideCollapseTool || me.header === false)) {
37801             me.collapseDirection = me.collapseDirection || me.headerPosition || 'top';
37802             me.collapseTool = me.expandTool = me.createComponent({
37803                 xtype: 'tool',
37804                 type: 'collapse-' + me.collapseDirection,
37805                 expandType: me.getOppositeDirection(me.collapseDirection),
37806                 handler: me.toggleCollapse,
37807                 scope: me
37808             });
37809
37810             
37811             if (me.collapseFirst) {
37812                 me.tools.unshift(me.collapseTool);
37813             }
37814         }
37815
37816         
37817         me.addTools();
37818
37819         
37820         if (me.closable) {
37821             me.addClsWithUI('closable');
37822             me.addTool({
37823                 type: 'close',
37824                 handler: Ext.Function.bind(me.close, this, [])
37825             });
37826         }
37827
37828         
37829         if (me.collapseTool && !me.collapseFirst) {
37830             me.tools.push(me.collapseTool);
37831         }
37832     },
37833
37834     
37835     addTools: Ext.emptyFn,
37836
37837     
37838     close: function() {
37839         if (this.fireEvent('beforeclose', this) !== false) {
37840             this.doClose();
37841         }
37842     },
37843
37844     
37845     doClose: function() {
37846         this.fireEvent('close', this);
37847         this[this.closeAction]();
37848     },
37849
37850     onRender: function(ct, position) {
37851         var me = this,
37852             topContainer;
37853
37854         
37855         
37856         me.initTools();
37857
37858         
37859         me.updateHeader();
37860
37861         
37862         me.callParent(arguments);
37863     },
37864
37865     afterRender: function() {
37866         var me = this;
37867
37868         me.callParent(arguments);
37869
37870         
37871         
37872         
37873         if (me.collapsed) {
37874             me.collapsed = false;
37875             me.collapse(null, false, true);
37876         }
37877     },
37878
37879     
37880     updateHeader: function(force) {
37881         var me = this,
37882             header = me.header,
37883             title = me.title,
37884             tools = me.tools;
37885
37886         if (!me.preventHeader && (force || title || (tools && tools.length))) {
37887             if (!header) {
37888                 header = me.header = Ext.create('Ext.panel.Header', {
37889                     title       : title,
37890                     orientation : (me.headerPosition == 'left' || me.headerPosition == 'right') ? 'vertical' : 'horizontal',
37891                     dock        : me.headerPosition || 'top',
37892                     textCls     : me.headerTextCls,
37893                     iconCls     : me.iconCls,
37894                     baseCls     : me.baseCls + '-header',
37895                     tools       : tools,
37896                     ui          : me.ui,
37897                     indicateDrag: me.draggable,
37898                     border      : me.border,
37899                     frame       : me.frame && me.frameHeader,
37900                     ignoreParentFrame : me.frame || me.overlapHeader,
37901                     ignoreBorderManagement: me.frame || me.ignoreHeaderBorderManagement,
37902                     listeners   : me.collapsible && me.titleCollapse ? {
37903                         click: me.toggleCollapse,
37904                         scope: me
37905                     } : null
37906                 });
37907                 me.addDocked(header, 0);
37908
37909                 
37910                 
37911                 me.tools = header.tools;
37912             }
37913             header.show();
37914             me.initHeaderAria();
37915         } else if (header) {
37916             header.hide();
37917         }
37918     },
37919
37920     
37921     setUI: function(ui) {
37922         var me = this;
37923
37924         me.callParent(arguments);
37925
37926         if (me.header) {
37927             me.header.setUI(ui);
37928         }
37929     },
37930
37931     
37932     getContentTarget: function() {
37933         return this.body;
37934     },
37935
37936     getTargetEl: function() {
37937         return this.body || this.frameBody || this.el;
37938     },
37939
37940     
37941
37942     
37943     isVisible: function(deep){
37944         var me = this;
37945         if (me.collapsed && me.placeholder) {
37946             return me.placeholder.isVisible(deep);
37947         }
37948         return me.callParent(arguments);
37949     },
37950
37951     
37952     onHide: function(){
37953         var me = this;
37954         if (me.collapsed && me.placeholder) {
37955             me.placeholder.hide();
37956         } else {
37957             me.callParent(arguments);
37958         }
37959     },
37960
37961     
37962     onShow: function(){
37963         var me = this;
37964         if (me.collapsed && me.placeholder) {
37965             
37966             me.hidden = true;
37967             me.placeholder.show();
37968         } else {
37969             me.callParent(arguments);
37970         }
37971     },
37972
37973     addTool: function(tool) {
37974         var me = this,
37975             header = me.header;
37976
37977         if (Ext.isArray(tool)) {
37978             Ext.each(tool, me.addTool, me);
37979             return;
37980         }
37981         me.tools.push(tool);
37982         if (header) {
37983             header.addTool(tool);
37984         }
37985         me.updateHeader();
37986     },
37987
37988     getOppositeDirection: function(d) {
37989         var c = Ext.Component;
37990         switch (d) {
37991             case c.DIRECTION_TOP:
37992                 return c.DIRECTION_BOTTOM;
37993             case c.DIRECTION_RIGHT:
37994                 return c.DIRECTION_LEFT;
37995             case c.DIRECTION_BOTTOM:
37996                 return c.DIRECTION_TOP;
37997             case c.DIRECTION_LEFT:
37998                 return c.DIRECTION_RIGHT;
37999         }
38000     },
38001
38002     
38003     collapse: function(direction, animate,  internal) {
38004         var me = this,
38005             c = Ext.Component,
38006             height = me.getHeight(),
38007             width = me.getWidth(),
38008             frameInfo,
38009             newSize = 0,
38010             dockedItems = me.dockedItems.items,
38011             dockedItemCount = dockedItems.length,
38012             i = 0,
38013             comp,
38014             pos,
38015             anim = {
38016                 from: {
38017                     height: height,
38018                     width: width
38019                 },
38020                 to: {
38021                     height: height,
38022                     width: width
38023                 },
38024                 listeners: {
38025                     afteranimate: me.afterCollapse,
38026                     scope: me
38027                 },
38028                 duration: Ext.Number.from(animate, Ext.fx.Anim.prototype.duration)
38029             },
38030             reExpander,
38031             reExpanderOrientation,
38032             reExpanderDock,
38033             getDimension,
38034             collapseDimension;
38035
38036         if (!direction) {
38037             direction = me.collapseDirection;
38038         }
38039
38040         
38041         if (internal) {
38042             animate = false;
38043         } else if (me.collapsed || me.fireEvent('beforecollapse', me, direction, animate) === false) {
38044             return false;
38045         }
38046
38047         reExpanderDock = direction;
38048         me.expandDirection = me.getOppositeDirection(direction);
38049
38050         
38051         me.hiddenDocked = [];
38052
38053         switch (direction) {
38054             case c.DIRECTION_TOP:
38055             case c.DIRECTION_BOTTOM:
38056                 reExpanderOrientation = 'horizontal';
38057                 collapseDimension = 'height';
38058                 getDimension = 'getHeight';
38059
38060                 
38061                 
38062                 for (; i < dockedItemCount; i++) {
38063                     comp = dockedItems[i];
38064                     if (comp.isVisible()) {
38065                         if (comp.isXType('header', true) && (!comp.dock || comp.dock == 'top' || comp.dock == 'bottom')) {
38066                             reExpander = comp;
38067                         } else {
38068                             me.hiddenDocked.push(comp);
38069                         }
38070                     } else if (comp === me.reExpander) {
38071                         reExpander = comp;
38072                     }
38073                 }
38074
38075                 if (direction == Ext.Component.DIRECTION_BOTTOM) {
38076                     pos = me.getPosition()[1] - Ext.fly(me.el.dom.offsetParent).getRegion().top;
38077                     anim.from.top = pos;
38078                 }
38079                 break;
38080
38081             case c.DIRECTION_LEFT:
38082             case c.DIRECTION_RIGHT:
38083                 reExpanderOrientation = 'vertical';
38084                 collapseDimension = 'width';
38085                 getDimension = 'getWidth';
38086
38087                 
38088                 
38089                 for (; i < dockedItemCount; i++) {
38090                     comp = dockedItems[i];
38091                     if (comp.isVisible()) {
38092                         if (comp.isHeader && (comp.dock == 'left' || comp.dock == 'right')) {
38093                             reExpander = comp;
38094                         } else {
38095                             me.hiddenDocked.push(comp);
38096                         }
38097                     } else if (comp === me.reExpander) {
38098                         reExpander = comp;
38099                     }
38100                 }
38101
38102                 if (direction == Ext.Component.DIRECTION_RIGHT) {
38103                     pos = me.getPosition()[0] - Ext.fly(me.el.dom.offsetParent).getRegion().left;
38104                     anim.from.left = pos;
38105                 }
38106                 break;
38107
38108             default:
38109                 throw('Panel collapse must be passed a valid Component collapse direction');
38110         }
38111
38112         
38113         if (animate && me.collapseTool) {
38114             me.collapseTool.disable();
38115         }
38116
38117         
38118         me.addClsWithUI(me.collapsedCls);
38119         
38120         
38121         
38122
38123         
38124         if (reExpander && reExpander.rendered) {
38125
38126             
38127             reExpander.addClsWithUI(me.collapsedCls);
38128             reExpander.addClsWithUI(me.collapsedCls + '-' + reExpander.dock);
38129             if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
38130                 reExpander.addClsWithUI(me.collapsedCls + '-border-' + reExpander.dock);
38131             }
38132
38133             frameInfo = reExpander.getFrameInfo();
38134
38135             
38136             newSize = reExpander[getDimension]() + (frameInfo ? frameInfo[direction] : 0);
38137
38138             
38139             reExpander.removeClsWithUI(me.collapsedCls);
38140             reExpander.removeClsWithUI(me.collapsedCls + '-' + reExpander.dock);
38141             if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
38142                 reExpander.removeClsWithUI(me.collapsedCls + '-border-' + reExpander.dock);
38143             }
38144         }
38145         
38146         else {
38147             reExpander = {
38148                 hideMode: 'offsets',
38149                 temporary: true,
38150                 title: me.title,
38151                 orientation: reExpanderOrientation,
38152                 dock: reExpanderDock,
38153                 textCls: me.headerTextCls,
38154                 iconCls: me.iconCls,
38155                 baseCls: me.baseCls + '-header',
38156                 ui: me.ui,
38157                 frame: me.frame && me.frameHeader,
38158                 ignoreParentFrame: me.frame || me.overlapHeader,
38159                 indicateDrag: me.draggable,
38160                 cls: me.baseCls + '-collapsed-placeholder ' + ' ' + Ext.baseCSSPrefix + 'docked ' + me.baseCls + '-' + me.ui + '-collapsed',
38161                 renderTo: me.el
38162             };
38163             if (!me.hideCollapseTool) {
38164                 reExpander[(reExpander.orientation == 'horizontal') ? 'tools' : 'items'] = [{
38165                     xtype: 'tool',
38166                     type: 'expand-' + me.expandDirection,
38167                     handler: me.toggleCollapse,
38168                     scope: me
38169                 }];
38170             }
38171
38172             
38173             
38174             reExpander = me.reExpander = Ext.create('Ext.panel.Header', reExpander);
38175             newSize = reExpander[getDimension]() + ((reExpander.frame) ? reExpander.frameSize[direction] : 0);
38176             reExpander.hide();
38177
38178             
38179             me.insertDocked(0, reExpander);
38180         }
38181
38182         me.reExpander = reExpander;
38183         me.reExpander.addClsWithUI(me.collapsedCls);
38184         me.reExpander.addClsWithUI(me.collapsedCls + '-' + reExpander.dock);
38185         if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
38186             me.reExpander.addClsWithUI(me.collapsedCls + '-border-' + me.reExpander.dock);
38187         }
38188
38189         
38190         if (direction == Ext.Component.DIRECTION_RIGHT) {
38191             anim.to.left = pos + (width - newSize);
38192         } else if (direction == Ext.Component.DIRECTION_BOTTOM) {
38193             anim.to.top = pos + (height - newSize);
38194         }
38195
38196         
38197         anim.to[collapseDimension] = newSize;
38198
38199         
38200         
38201         
38202         
38203         
38204         if (!me.collapseMemento) {
38205             me.collapseMemento = new Ext.util.Memento(me);
38206         }
38207         me.collapseMemento.capture(['width', 'height', 'minWidth', 'minHeight', 'layoutManagedHeight', 'layoutManagedWidth']);
38208
38209         
38210         me.savedFlex = me.flex;
38211         me.minWidth = 0;
38212         me.minHeight = 0;
38213         delete me.flex;
38214         me.suspendLayout = true;
38215
38216         if (animate) {
38217             me.animate(anim);
38218         } else {
38219             me.setSize(anim.to.width, anim.to.height);
38220             if (Ext.isDefined(anim.to.left) || Ext.isDefined(anim.to.top)) {
38221                 me.setPosition(anim.to.left, anim.to.top);
38222             }
38223             me.afterCollapse(false, internal);
38224         }
38225         return me;
38226     },
38227
38228     afterCollapse: function(animated, internal) {
38229         var me = this,
38230             i = 0,
38231             l = me.hiddenDocked.length;
38232
38233         me.collapseMemento.restore(['minWidth', 'minHeight']);
38234
38235         
38236         
38237         
38238         if (Ext.Component.VERTICAL_DIRECTION_Re.test(me.expandDirection)) {
38239             me.layoutManagedHeight = 2;
38240             me.collapseMemento.restore('width', false);
38241         } else {
38242             me.layoutManagedWidth = 2;
38243             me.collapseMemento.restore('height', false);
38244         }
38245
38246         
38247         
38248         me.saveScrollTop = me.body.dom.scrollTop;
38249         me.body.setStyle('display', 'none');
38250
38251         for (; i < l; i++) {
38252             me.hiddenDocked[i].hide();
38253         }
38254         if (me.reExpander) {
38255             me.reExpander.updateFrame();
38256             me.reExpander.show();
38257         }
38258         me.collapsed = true;
38259         me.suspendLayout = false;
38260
38261         if (!internal) {
38262             if (me.ownerCt) {
38263                 
38264                 
38265                 if (animated) {
38266                     me.ownerCt.layout.layout();
38267                 }
38268             } else if (me.reExpander.temporary) {
38269                 me.doComponentLayout();
38270             }
38271         }
38272
38273         if (me.resizer) {
38274             me.resizer.disable();
38275         }
38276
38277         
38278         if (me.collapseTool) {
38279             me.collapseTool.setType('expand-' + me.expandDirection);
38280         }
38281         if (!internal) {
38282             me.fireEvent('collapse', me);
38283         }
38284
38285         
38286         if (animated && me.collapseTool) {
38287             me.collapseTool.enable();
38288         }
38289     },
38290
38291     
38292     expand: function(animate) {
38293         var me = this;
38294         if (!me.collapsed || me.fireEvent('beforeexpand', me, animate) === false) {
38295             return false;
38296         }
38297
38298         var i = 0,
38299             l = me.hiddenDocked.length,
38300             direction = me.expandDirection,
38301             height = me.getHeight(),
38302             width = me.getWidth(),
38303             pos, anim;
38304
38305         
38306         if (animate && me.collapseTool) {
38307             me.collapseTool.disable();
38308         }
38309
38310         
38311         
38312         for (; i < l; i++) {
38313             me.hiddenDocked[i].hidden = false;
38314             me.hiddenDocked[i].el.show();
38315         }
38316         if (me.reExpander) {
38317             if (me.reExpander.temporary) {
38318                 me.reExpander.hide();
38319             } else {
38320                 me.reExpander.removeClsWithUI(me.collapsedCls);
38321                 me.reExpander.removeClsWithUI(me.collapsedCls + '-' + me.reExpander.dock);
38322                 if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
38323                     me.reExpander.removeClsWithUI(me.collapsedCls + '-border-' + me.reExpander.dock);
38324                 }
38325                 me.reExpander.updateFrame();
38326             }
38327         }
38328
38329         
38330         if (me.collapseTool) {
38331             me.collapseTool.setType('collapse-' + me.collapseDirection);
38332         }
38333
38334         
38335         me.body.setStyle('display', '');
38336         me.body.dom.scrollTop = me.saveScrollTop;
38337
38338         
38339         me.collapsed = false;
38340
38341         
38342         me.removeClsWithUI(me.collapsedCls);
38343         
38344         
38345         
38346
38347         anim = {
38348             to: {
38349             },
38350             from: {
38351                 height: height,
38352                 width: width
38353             },
38354             listeners: {
38355                 afteranimate: me.afterExpand,
38356                 scope: me
38357             }
38358         };
38359
38360         if ((direction == Ext.Component.DIRECTION_TOP) || (direction == Ext.Component.DIRECTION_BOTTOM)) {
38361
38362             
38363             
38364             me.collapseMemento.restore('height', false);
38365
38366             
38367             if (me.height === undefined) {
38368                 me.setCalculatedSize(me.width, null);
38369                 anim.to.height = me.getHeight();
38370
38371                 
38372                 me.setCalculatedSize(me.width, anim.from.height);
38373             }
38374             
38375             
38376             else if (me.savedFlex) {
38377                 me.flex = me.savedFlex;
38378                 anim.to.height = me.ownerCt.layout.calculateChildBox(me).height;
38379                 delete me.flex;
38380             }
38381             
38382             else {
38383                 anim.to.height = me.height;
38384             }
38385
38386             
38387             if (direction == Ext.Component.DIRECTION_TOP) {
38388                 pos = me.getPosition()[1] - Ext.fly(me.el.dom.offsetParent).getRegion().top;
38389                 anim.from.top = pos;
38390                 anim.to.top = pos - (anim.to.height - height);
38391             }
38392         } else if ((direction == Ext.Component.DIRECTION_LEFT) || (direction == Ext.Component.DIRECTION_RIGHT)) {
38393
38394             
38395             
38396             me.collapseMemento.restore('width', false);
38397
38398             
38399             if (me.width === undefined) {
38400                 me.setCalculatedSize(null, me.height);
38401                 anim.to.width = me.getWidth();
38402
38403                 
38404                 me.setCalculatedSize(anim.from.width, me.height);
38405             }
38406             
38407             
38408             else if (me.savedFlex) {
38409                 me.flex = me.savedFlex;
38410                 anim.to.width = me.ownerCt.layout.calculateChildBox(me).width;
38411                 delete me.flex;
38412             }
38413             
38414             else {
38415                 anim.to.width = me.width;
38416             }
38417
38418             
38419             if (direction == Ext.Component.DIRECTION_LEFT) {
38420                 pos = me.getPosition()[0] - Ext.fly(me.el.dom.offsetParent).getRegion().left;
38421                 anim.from.left = pos;
38422                 anim.to.left = pos - (anim.to.width - width);
38423             }
38424         }
38425
38426         if (animate) {
38427             me.animate(anim);
38428         } else {
38429             me.setCalculatedSize(anim.to.width, anim.to.height);
38430             if (anim.to.x) {
38431                 me.setLeft(anim.to.x);
38432             }
38433             if (anim.to.y) {
38434                 me.setTop(anim.to.y);
38435             }
38436             me.afterExpand(false);
38437         }
38438
38439         return me;
38440     },
38441
38442     afterExpand: function(animated) {
38443         var me = this;
38444
38445         
38446         if (me.savedFlex) {
38447             me.flex = me.savedFlex;
38448             delete me.savedFlex;
38449             delete me.width;
38450             delete me.height;
38451         }
38452
38453         
38454         if (me.collapseMemento) {
38455             me.collapseMemento.restoreAll();
38456         }
38457
38458         if (animated && me.ownerCt) {
38459             
38460             
38461             Ext.defer(me.ownerCt.doLayout, Ext.isIE6 ? 1 : 0, me);
38462         }
38463
38464         if (me.resizer) {
38465             me.resizer.enable();
38466         }
38467
38468         me.fireEvent('expand', me);
38469
38470         
38471         if (animated && me.collapseTool) {
38472             me.collapseTool.enable();
38473         }
38474     },
38475
38476     
38477     toggleCollapse: function() {
38478         if (this.collapsed) {
38479             this.expand(this.animCollapse);
38480         } else {
38481             this.collapse(this.collapseDirection, this.animCollapse);
38482         }
38483         return this;
38484     },
38485
38486     
38487     getKeyMap : function(){
38488         if(!this.keyMap){
38489             this.keyMap = Ext.create('Ext.util.KeyMap', this.el, this.keys);
38490         }
38491         return this.keyMap;
38492     },
38493
38494     
38495     initDraggable : function(){
38496         
38497         this.dd = Ext.create('Ext.panel.DD', this, Ext.isBoolean(this.draggable) ? null : this.draggable);
38498     },
38499
38500     
38501     ghostTools : function() {
38502         var tools = [],
38503             headerTools = this.header.query('tool[hidden=false]');
38504
38505         if (headerTools.length) {
38506             Ext.each(headerTools, function(tool) {
38507                 
38508                 
38509                 
38510                 
38511                 tools.push({
38512                     type: tool.type
38513                 });
38514             });
38515         } else {
38516             tools = [{
38517                 type: 'placeholder'
38518             }];
38519         }
38520         return tools;
38521     },
38522
38523     
38524     ghost: function(cls) {
38525         var me = this,
38526             ghostPanel = me.ghostPanel,
38527             box = me.getBox(),
38528             header;
38529
38530         if (!ghostPanel) {
38531             ghostPanel = Ext.create('Ext.panel.Panel', {
38532                 renderTo: me.floating ? me.el.dom.parentNode : document.body,
38533                 floating: {
38534                     shadow: false
38535                 },
38536                 frame: Ext.supports.CSS3BorderRadius ? me.frame : false,
38537                 overlapHeader: me.overlapHeader,
38538                 headerPosition: me.headerPosition,
38539                 baseCls: me.baseCls,
38540                 cls: me.baseCls + '-ghost ' + (cls ||'')
38541             });
38542             me.ghostPanel = ghostPanel;
38543         }
38544         ghostPanel.floatParent = me.floatParent;
38545         if (me.floating) {
38546             ghostPanel.setZIndex(Ext.Number.from(me.el.getStyle('zIndex'), 0));
38547         } else {
38548             ghostPanel.toFront();
38549         }
38550         header = ghostPanel.header;
38551         
38552         if (header) {
38553             header.suspendLayout = true;
38554             Ext.Array.forEach(header.query('tool'), function(tool){
38555                 header.remove(tool);
38556             });
38557             header.suspendLayout = false;
38558         }
38559         ghostPanel.addTool(me.ghostTools());
38560         ghostPanel.setTitle(me.title);
38561         ghostPanel.setIconCls(me.iconCls);
38562
38563         ghostPanel.el.show();
38564         ghostPanel.setPosition(box.x, box.y);
38565         ghostPanel.setSize(box.width, box.height);
38566         me.el.hide();
38567         if (me.floatingItems) {
38568             me.floatingItems.hide();
38569         }
38570         return ghostPanel;
38571     },
38572
38573     
38574     unghost: function(show, matchPosition) {
38575         var me = this;
38576         if (!me.ghostPanel) {
38577             return;
38578         }
38579         if (show !== false) {
38580             me.el.show();
38581             if (matchPosition !== false) {
38582                 me.setPosition(me.ghostPanel.getPosition());
38583             }
38584             if (me.floatingItems) {
38585                 me.floatingItems.show();
38586             }
38587             Ext.defer(me.focus, 10, me);
38588         }
38589         me.ghostPanel.el.hide();
38590     },
38591
38592     initResizable: function(resizable) {
38593         if (this.collapsed) {
38594             resizable.disabled = true;
38595         }
38596         this.callParent([resizable]);
38597     }
38598 }, function(){
38599     this.prototype.animCollapse = Ext.enableFx;
38600 });
38601
38602
38603
38604 Ext.define('Ext.layout.component.Tip', {
38605
38606     
38607
38608     alias: ['layout.tip'],
38609
38610     extend: 'Ext.layout.component.Dock',
38611
38612     
38613
38614     type: 'tip',
38615     
38616     onLayout: function(width, height) {
38617         var me = this,
38618             owner = me.owner,
38619             el = owner.el,
38620             minWidth,
38621             maxWidth,
38622             naturalWidth,
38623             constrainedWidth,
38624             xy = el.getXY();
38625
38626         
38627         el.setXY([-9999,-9999]);
38628
38629         
38630         this.callParent(arguments);
38631
38632         
38633         if (!Ext.isNumber(width)) {
38634             minWidth = owner.minWidth;
38635             maxWidth = owner.maxWidth;
38636             
38637             if (Ext.isStrict && (Ext.isIE6 || Ext.isIE7)) {
38638                 constrainedWidth = me.doAutoWidth();
38639             } else {
38640                 naturalWidth = el.getWidth();
38641             }
38642             if (naturalWidth < minWidth) {
38643                 constrainedWidth = minWidth;
38644             }
38645             else if (naturalWidth > maxWidth) {
38646                 constrainedWidth = maxWidth;
38647             }
38648             if (constrainedWidth) {
38649                 this.callParent([constrainedWidth, height]);
38650             }
38651         }
38652
38653         
38654         el.setXY(xy);
38655     },
38656     
38657     doAutoWidth: function(){
38658         var me = this,
38659             owner = me.owner,
38660             body = owner.body,
38661             width = body.getTextWidth();
38662             
38663         if (owner.header) {
38664             width = Math.max(width, owner.header.getWidth());
38665         }
38666         if (!Ext.isDefined(me.frameWidth)) {
38667             me.frameWidth = owner.el.getWidth() - body.getWidth();
38668         }
38669         width += me.frameWidth + body.getPadding('lr');
38670         return width;
38671     }
38672 });
38673
38674
38675 Ext.define('Ext.tip.Tip', {
38676     extend: 'Ext.panel.Panel',
38677     requires: [ 'Ext.layout.component.Tip' ],
38678     alternateClassName: 'Ext.Tip',
38679     
38680     
38681     
38682     minWidth : 40,
38683     
38684     maxWidth : 300,
38685     
38686     shadow : "sides",
38687
38688     
38689     defaultAlign : "tl-bl?",
38690     
38691     constrainPosition : true,
38692
38693     
38694     frame: false,
38695
38696     
38697     autoRender: true,
38698     hidden: true,
38699     baseCls: Ext.baseCSSPrefix + 'tip',
38700     floating: {
38701         shadow: true,
38702         shim: true,
38703         constrain: true
38704     },
38705     focusOnToFront: false,
38706     componentLayout: 'tip',
38707
38708     
38709     closeAction: 'hide',
38710
38711     ariaRole: 'tooltip',
38712
38713     initComponent: function() {
38714         var me = this;
38715
38716         me.floating = Ext.apply({}, {shadow: me.shadow}, me.self.prototype.floating);
38717         me.callParent(arguments);
38718
38719         
38720         me.constrain = me.constrain || me.constrainPosition;
38721     },
38722
38723     
38724     showAt : function(xy){
38725         var me = this;
38726         this.callParent(arguments);
38727         
38728         if (me.isVisible()) {
38729             me.setPagePosition(xy[0], xy[1]);
38730             if (me.constrainPosition || me.constrain) {
38731                 me.doConstrain();
38732             }
38733             me.toFront(true);
38734         }
38735     },
38736
38737     
38738     showBy : function(el, pos) {
38739         this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
38740     },
38741
38742     
38743     initDraggable : function(){
38744         var me = this;
38745         me.draggable = {
38746             el: me.getDragEl(),
38747             delegate: me.header.el,
38748             constrain: me,
38749             constrainTo: me.el.getScopeParent()
38750         };
38751         
38752         Ext.Component.prototype.initDraggable.call(me);
38753     },
38754
38755     
38756     ghost: undefined,
38757     unghost: undefined
38758 });
38759
38760
38761 Ext.define('Ext.tip.ToolTip', {
38762     extend: 'Ext.tip.Tip',
38763     alias: 'widget.tooltip',
38764     alternateClassName: 'Ext.ToolTip',
38765     
38766     
38767     
38768     
38769     showDelay: 500,
38770     
38771     hideDelay: 200,
38772     
38773     dismissDelay: 5000,
38774     
38775     
38776     trackMouse: false,
38777     
38778     
38779     anchorToTarget: true,
38780     
38781     anchorOffset: 0,
38782     
38783
38784     
38785     targetCounter: 0,
38786     quickShowInterval: 250,
38787
38788     
38789     initComponent: function() {
38790         var me = this;
38791         me.callParent(arguments);
38792         me.lastActive = new Date();
38793         me.setTarget(me.target);
38794         me.origAnchor = me.anchor;
38795     },
38796
38797     
38798     onRender: function(ct, position) {
38799         var me = this;
38800         me.callParent(arguments);
38801         me.anchorCls = Ext.baseCSSPrefix + 'tip-anchor-' + me.getAnchorPosition();
38802         me.anchorEl = me.el.createChild({
38803             cls: Ext.baseCSSPrefix + 'tip-anchor ' + me.anchorCls
38804         });
38805     },
38806
38807     
38808     afterRender: function() {
38809         var me = this,
38810             zIndex;
38811
38812         me.callParent(arguments);
38813         zIndex = parseInt(me.el.getZIndex(), 10) || 0;
38814         me.anchorEl.setStyle('z-index', zIndex + 1).setVisibilityMode(Ext.Element.DISPLAY);
38815     },
38816
38817     
38818     setTarget: function(target) {
38819         var me = this,
38820             t = Ext.get(target),
38821             tg;
38822
38823         if (me.target) {
38824             tg = Ext.get(me.target);
38825             me.mun(tg, 'mouseover', me.onTargetOver, me);
38826             me.mun(tg, 'mouseout', me.onTargetOut, me);
38827             me.mun(tg, 'mousemove', me.onMouseMove, me);
38828         }
38829
38830         me.target = t;
38831         if (t) {
38832
38833             me.mon(t, {
38834                 
38835                 
38836                 freezeEvent: true,
38837
38838                 mouseover: me.onTargetOver,
38839                 mouseout: me.onTargetOut,
38840                 mousemove: me.onMouseMove,
38841                 scope: me
38842             });
38843         }
38844         if (me.anchor) {
38845             me.anchorTarget = me.target;
38846         }
38847     },
38848
38849     
38850     onMouseMove: function(e) {
38851         var me = this,
38852             t = me.delegate ? e.getTarget(me.delegate) : me.triggerElement = true,
38853             xy;
38854         if (t) {
38855             me.targetXY = e.getXY();
38856             if (t === me.triggerElement) {
38857                 if (!me.hidden && me.trackMouse) {
38858                     xy = me.getTargetXY();
38859                     if (me.constrainPosition) {
38860                         xy = me.el.adjustForConstraints(xy, me.el.getScopeParent());
38861                     }
38862                     me.setPagePosition(xy);
38863                 }
38864             } else {
38865                 me.hide();
38866                 me.lastActive = new Date(0);
38867                 me.onTargetOver(e);
38868             }
38869         } else if ((!me.closable && me.isVisible()) && me.autoHide !== false) {
38870             me.hide();
38871         }
38872     },
38873
38874     
38875     getTargetXY: function() {
38876         var me = this,
38877             mouseOffset;
38878         if (me.delegate) {
38879             me.anchorTarget = me.triggerElement;
38880         }
38881         if (me.anchor) {
38882             me.targetCounter++;
38883                 var offsets = me.getOffsets(),
38884                     xy = (me.anchorToTarget && !me.trackMouse) ? me.el.getAlignToXY(me.anchorTarget, me.getAnchorAlign()) : me.targetXY,
38885                     dw = Ext.Element.getViewWidth() - 5,
38886                     dh = Ext.Element.getViewHeight() - 5,
38887                     de = document.documentElement,
38888                     bd = document.body,
38889                     scrollX = (de.scrollLeft || bd.scrollLeft || 0) + 5,
38890                     scrollY = (de.scrollTop || bd.scrollTop || 0) + 5,
38891                     axy = [xy[0] + offsets[0], xy[1] + offsets[1]],
38892                     sz = me.getSize(),
38893                     constrainPosition = me.constrainPosition;
38894
38895             me.anchorEl.removeCls(me.anchorCls);
38896
38897             if (me.targetCounter < 2 && constrainPosition) {
38898                 if (axy[0] < scrollX) {
38899                     if (me.anchorToTarget) {
38900                         me.defaultAlign = 'l-r';
38901                         if (me.mouseOffset) {
38902                             me.mouseOffset[0] *= -1;
38903                         }
38904                     }
38905                     me.anchor = 'left';
38906                     return me.getTargetXY();
38907                 }
38908                 if (axy[0] + sz.width > dw) {
38909                     if (me.anchorToTarget) {
38910                         me.defaultAlign = 'r-l';
38911                         if (me.mouseOffset) {
38912                             me.mouseOffset[0] *= -1;
38913                         }
38914                     }
38915                     me.anchor = 'right';
38916                     return me.getTargetXY();
38917                 }
38918                 if (axy[1] < scrollY) {
38919                     if (me.anchorToTarget) {
38920                         me.defaultAlign = 't-b';
38921                         if (me.mouseOffset) {
38922                             me.mouseOffset[1] *= -1;
38923                         }
38924                     }
38925                     me.anchor = 'top';
38926                     return me.getTargetXY();
38927                 }
38928                 if (axy[1] + sz.height > dh) {
38929                     if (me.anchorToTarget) {
38930                         me.defaultAlign = 'b-t';
38931                         if (me.mouseOffset) {
38932                             me.mouseOffset[1] *= -1;
38933                         }
38934                     }
38935                     me.anchor = 'bottom';
38936                     return me.getTargetXY();
38937                 }
38938             }
38939
38940             me.anchorCls = Ext.baseCSSPrefix + 'tip-anchor-' + me.getAnchorPosition();
38941             me.anchorEl.addCls(me.anchorCls);
38942             me.targetCounter = 0;
38943             return axy;
38944         } else {
38945             mouseOffset = me.getMouseOffset();
38946             return (me.targetXY) ? [me.targetXY[0] + mouseOffset[0], me.targetXY[1] + mouseOffset[1]] : mouseOffset;
38947         }
38948     },
38949
38950     getMouseOffset: function() {
38951         var me = this,
38952         offset = me.anchor ? [0, 0] : [15, 18];
38953         if (me.mouseOffset) {
38954             offset[0] += me.mouseOffset[0];
38955             offset[1] += me.mouseOffset[1];
38956         }
38957         return offset;
38958     },
38959
38960     
38961     getAnchorPosition: function() {
38962         var me = this,
38963             m;
38964         if (me.anchor) {
38965             me.tipAnchor = me.anchor.charAt(0);
38966         } else {
38967             m = me.defaultAlign.match(/^([a-z]+)-([a-z]+)(\?)?$/);
38968             me.tipAnchor = m[1].charAt(0);
38969         }
38970
38971         switch (me.tipAnchor) {
38972         case 't':
38973             return 'top';
38974         case 'b':
38975             return 'bottom';
38976         case 'r':
38977             return 'right';
38978         }
38979         return 'left';
38980     },
38981
38982     
38983     getAnchorAlign: function() {
38984         switch (this.anchor) {
38985         case 'top':
38986             return 'tl-bl';
38987         case 'left':
38988             return 'tl-tr';
38989         case 'right':
38990             return 'tr-tl';
38991         default:
38992             return 'bl-tl';
38993         }
38994     },
38995
38996     
38997     getOffsets: function() {
38998         var me = this,
38999             mouseOffset,
39000             offsets,
39001             ap = me.getAnchorPosition().charAt(0);
39002         if (me.anchorToTarget && !me.trackMouse) {
39003             switch (ap) {
39004             case 't':
39005                 offsets = [0, 9];
39006                 break;
39007             case 'b':
39008                 offsets = [0, -13];
39009                 break;
39010             case 'r':
39011                 offsets = [ - 13, 0];
39012                 break;
39013             default:
39014                 offsets = [9, 0];
39015                 break;
39016             }
39017         } else {
39018             switch (ap) {
39019             case 't':
39020                 offsets = [ - 15 - me.anchorOffset, 30];
39021                 break;
39022             case 'b':
39023                 offsets = [ - 19 - me.anchorOffset, -13 - me.el.dom.offsetHeight];
39024                 break;
39025             case 'r':
39026                 offsets = [ - 15 - me.el.dom.offsetWidth, -13 - me.anchorOffset];
39027                 break;
39028             default:
39029                 offsets = [25, -13 - me.anchorOffset];
39030                 break;
39031             }
39032         }
39033         mouseOffset = me.getMouseOffset();
39034         offsets[0] += mouseOffset[0];
39035         offsets[1] += mouseOffset[1];
39036
39037         return offsets;
39038     },
39039
39040     
39041     onTargetOver: function(e) {
39042         var me = this,
39043             t;
39044
39045         if (me.disabled || e.within(me.target.dom, true)) {
39046             return;
39047         }
39048         t = e.getTarget(me.delegate);
39049         if (t) {
39050             me.triggerElement = t;
39051             me.clearTimer('hide');
39052             me.targetXY = e.getXY();
39053             me.delayShow();
39054         }
39055     },
39056
39057     
39058     delayShow: function() {
39059         var me = this;
39060         if (me.hidden && !me.showTimer) {
39061             if (Ext.Date.getElapsed(me.lastActive) < me.quickShowInterval) {
39062                 me.show();
39063             } else {
39064                 me.showTimer = Ext.defer(me.show, me.showDelay, me);
39065             }
39066         }
39067         else if (!me.hidden && me.autoHide !== false) {
39068             me.show();
39069         }
39070     },
39071
39072     
39073     onTargetOut: function(e) {
39074         var me = this;
39075         if (me.disabled || e.within(me.target.dom, true)) {
39076             return;
39077         }
39078         me.clearTimer('show');
39079         if (me.autoHide !== false) {
39080             me.delayHide();
39081         }
39082     },
39083
39084     
39085     delayHide: function() {
39086         var me = this;
39087         if (!me.hidden && !me.hideTimer) {
39088             me.hideTimer = Ext.defer(me.hide, me.hideDelay, me);
39089         }
39090     },
39091
39092     
39093     hide: function() {
39094         var me = this;
39095         me.clearTimer('dismiss');
39096         me.lastActive = new Date();
39097         if (me.anchorEl) {
39098             me.anchorEl.hide();
39099         }
39100         me.callParent(arguments);
39101         delete me.triggerElement;
39102     },
39103
39104     
39105     show: function() {
39106         var me = this;
39107
39108         
39109         
39110         this.callParent();
39111         if (this.hidden === false) {
39112             me.setPagePosition(-10000, -10000);
39113
39114             if (me.anchor) {
39115                 me.anchor = me.origAnchor;
39116             }
39117             me.showAt(me.getTargetXY());
39118
39119             if (me.anchor) {
39120                 me.syncAnchor();
39121                 me.anchorEl.show();
39122             } else {
39123                 me.anchorEl.hide();
39124             }
39125         }
39126     },
39127
39128     
39129     showAt: function(xy) {
39130         var me = this;
39131         me.lastActive = new Date();
39132         me.clearTimers();
39133
39134         
39135         if (!me.isVisible()) {
39136             this.callParent(arguments);
39137         }
39138
39139         
39140         if (me.isVisible()) {
39141             me.setPagePosition(xy[0], xy[1]);
39142             if (me.constrainPosition || me.constrain) {
39143                 me.doConstrain();
39144             }
39145             me.toFront(true);
39146         }
39147
39148         if (me.dismissDelay && me.autoHide !== false) {
39149             me.dismissTimer = Ext.defer(me.hide, me.dismissDelay, me);
39150         }
39151         if (me.anchor) {
39152             me.syncAnchor();
39153             if (!me.anchorEl.isVisible()) {
39154                 me.anchorEl.show();
39155             }
39156         } else {
39157             me.anchorEl.hide();
39158         }
39159     },
39160
39161     
39162     syncAnchor: function() {
39163         var me = this,
39164             anchorPos,
39165             targetPos,
39166             offset;
39167         switch (me.tipAnchor.charAt(0)) {
39168         case 't':
39169             anchorPos = 'b';
39170             targetPos = 'tl';
39171             offset = [20 + me.anchorOffset, 1];
39172             break;
39173         case 'r':
39174             anchorPos = 'l';
39175             targetPos = 'tr';
39176             offset = [ - 1, 12 + me.anchorOffset];
39177             break;
39178         case 'b':
39179             anchorPos = 't';
39180             targetPos = 'bl';
39181             offset = [20 + me.anchorOffset, -1];
39182             break;
39183         default:
39184             anchorPos = 'r';
39185             targetPos = 'tl';
39186             offset = [1, 12 + me.anchorOffset];
39187             break;
39188         }
39189         me.anchorEl.alignTo(me.el, anchorPos + '-' + targetPos, offset);
39190     },
39191
39192     
39193     setPagePosition: function(x, y) {
39194         var me = this;
39195         me.callParent(arguments);
39196         if (me.anchor) {
39197             me.syncAnchor();
39198         }
39199     },
39200
39201     
39202     clearTimer: function(name) {
39203         name = name + 'Timer';
39204         clearTimeout(this[name]);
39205         delete this[name];
39206     },
39207
39208     
39209     clearTimers: function() {
39210         var me = this;
39211         me.clearTimer('show');
39212         me.clearTimer('dismiss');
39213         me.clearTimer('hide');
39214     },
39215
39216     
39217     onShow: function() {
39218         var me = this;
39219         me.callParent();
39220         me.mon(Ext.getDoc(), 'mousedown', me.onDocMouseDown, me);
39221     },
39222
39223     
39224     onHide: function() {
39225         var me = this;
39226         me.callParent();
39227         me.mun(Ext.getDoc(), 'mousedown', me.onDocMouseDown, me);
39228     },
39229
39230     
39231     onDocMouseDown: function(e) {
39232         var me = this;
39233         if (me.autoHide !== true && !me.closable && !e.within(me.el.dom)) {
39234             me.disable();
39235             Ext.defer(me.doEnable, 100, me);
39236         }
39237     },
39238
39239     
39240     doEnable: function() {
39241         if (!this.isDestroyed) {
39242             this.enable();
39243         }
39244     },
39245
39246     
39247     onDisable: function() {
39248         this.callParent();
39249         this.clearTimers();
39250         this.hide();
39251     },
39252
39253     beforeDestroy: function() {
39254         var me = this;
39255         me.clearTimers();
39256         Ext.destroy(me.anchorEl);
39257         delete me.anchorEl;
39258         delete me.target;
39259         delete me.anchorTarget;
39260         delete me.triggerElement;
39261         me.callParent();
39262     },
39263
39264     
39265     onDestroy: function() {
39266         Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
39267         this.callParent();
39268     }
39269 });
39270
39271
39272 Ext.define('Ext.tip.QuickTip', {
39273     extend: 'Ext.tip.ToolTip',
39274     alternateClassName: 'Ext.QuickTip',
39275     
39276     
39277     interceptTitles : false,
39278
39279     
39280     title: '&#160;',
39281
39282     
39283     tagConfig : {
39284         namespace : "data-",
39285         attribute : "qtip",
39286         width : "qwidth",
39287         target : "target",
39288         title : "qtitle",
39289         hide : "hide",
39290         cls : "qclass",
39291         align : "qalign",
39292         anchor : "anchor"
39293     },
39294
39295     
39296     initComponent : function(){
39297         var me = this;
39298
39299         me.target = me.target || Ext.getDoc();
39300         me.targets = me.targets || {};
39301         me.callParent();
39302     },
39303
39304     
39305     register : function(config){
39306         var configs = Ext.isArray(config) ? config : arguments,
39307             i = 0,
39308             len = configs.length,
39309             target, j, targetLen;
39310
39311         for (; i < len; i++) {
39312             config = configs[i];
39313             target = config.target;
39314             if (target) {
39315                 if (Ext.isArray(target)) {
39316                     for (j = 0, targetLen = target.length; j < targetLen; j++) {
39317                         this.targets[Ext.id(target[j])] = config;
39318                     }
39319                 } else{
39320                     this.targets[Ext.id(target)] = config;
39321                 }
39322             }
39323         }
39324     },
39325
39326     
39327     unregister : function(el){
39328         delete this.targets[Ext.id(el)];
39329     },
39330
39331     
39332     cancelShow: function(el){
39333         var me = this,
39334             activeTarget = me.activeTarget;
39335
39336         el = Ext.get(el).dom;
39337         if (me.isVisible()) {
39338             if (activeTarget && activeTarget.el == el) {
39339                 me.hide();
39340             }
39341         } else if (activeTarget && activeTarget.el == el) {
39342             me.clearTimer('show');
39343         }
39344     },
39345
39346     
39347     getTipCfg: function(e) {
39348         var t = e.getTarget(),
39349             titleText = t.title,
39350             cfg;
39351
39352         if (this.interceptTitles && titleText && Ext.isString(titleText)) {
39353             t.qtip = titleText;
39354             t.removeAttribute("title");
39355             e.preventDefault();
39356             return {
39357                 text: titleText
39358             };
39359         }
39360         else {
39361             cfg = this.tagConfig;
39362             t = e.getTarget('[' + cfg.namespace + cfg.attribute + ']');
39363             if (t) {
39364                 return {
39365                     target: t,
39366                     text: t.getAttribute(cfg.namespace + cfg.attribute)
39367                 };
39368             }
39369         }
39370     },
39371
39372     
39373     onTargetOver : function(e){
39374         var me = this,
39375             target = e.getTarget(),
39376             elTarget,
39377             cfg,
39378             ns,
39379             tipConfig,
39380             autoHide;
39381
39382         if (me.disabled) {
39383             return;
39384         }
39385
39386         
39387         
39388         
39389         me.targetXY = e.getXY();
39390
39391         if(!target || target.nodeType !== 1 || target == document || target == document.body){
39392             return;
39393         }
39394
39395         if (me.activeTarget && ((target == me.activeTarget.el) || Ext.fly(me.activeTarget.el).contains(target))) {
39396             me.clearTimer('hide');
39397             me.show();
39398             return;
39399         }
39400
39401         if (target) {
39402             Ext.Object.each(me.targets, function(key, value) {
39403                 var targetEl = Ext.fly(value.target);
39404                 if (targetEl && (targetEl.dom === target || targetEl.contains(target))) {
39405                     elTarget = targetEl.dom;
39406                     return false;
39407                 }
39408             });
39409             if (elTarget) {
39410                 me.activeTarget = me.targets[elTarget.id];
39411                 me.activeTarget.el = target;
39412                 me.anchor = me.activeTarget.anchor;
39413                 if (me.anchor) {
39414                     me.anchorTarget = target;
39415                 }
39416                 me.delayShow();
39417                 return;
39418             }
39419         }
39420
39421         elTarget = Ext.get(target);
39422         cfg = me.tagConfig;
39423         ns = cfg.namespace;
39424         tipConfig = me.getTipCfg(e);
39425
39426         if (tipConfig) {
39427
39428             
39429             
39430             if (tipConfig.target) {
39431                 target = tipConfig.target;
39432                 elTarget = Ext.get(target);
39433             }
39434             autoHide = elTarget.getAttribute(ns + cfg.hide);
39435
39436             me.activeTarget = {
39437                 el: target,
39438                 text: tipConfig.text,
39439                 width: +elTarget.getAttribute(ns + cfg.width) || null,
39440                 autoHide: autoHide != "user" && autoHide !== 'false',
39441                 title: elTarget.getAttribute(ns + cfg.title),
39442                 cls: elTarget.getAttribute(ns + cfg.cls),
39443                 align: elTarget.getAttribute(ns + cfg.align)
39444
39445             };
39446             me.anchor = elTarget.getAttribute(ns + cfg.anchor);
39447             if (me.anchor) {
39448                 me.anchorTarget = target;
39449             }
39450             me.delayShow();
39451         }
39452     },
39453
39454     
39455     onTargetOut : function(e){
39456         var me = this;
39457
39458         
39459         if (me.activeTarget && e.within(me.activeTarget.el) && !me.getTipCfg(e)) {
39460             return;
39461         }
39462
39463         me.clearTimer('show');
39464         if (me.autoHide !== false) {
39465             me.delayHide();
39466         }
39467     },
39468
39469     
39470     showAt : function(xy){
39471         var me = this,
39472             target = me.activeTarget;
39473
39474         if (target) {
39475             if (!me.rendered) {
39476                 me.render(Ext.getBody());
39477                 me.activeTarget = target;
39478             }
39479             if (target.title) {
39480                 me.setTitle(target.title || '');
39481                 me.header.show();
39482             } else {
39483                 me.header.hide();
39484             }
39485             me.body.update(target.text);
39486             me.autoHide = target.autoHide;
39487             me.dismissDelay = target.dismissDelay || me.dismissDelay;
39488             if (me.lastCls) {
39489                 me.el.removeCls(me.lastCls);
39490                 delete me.lastCls;
39491             }
39492             if (target.cls) {
39493                 me.el.addCls(target.cls);
39494                 me.lastCls = target.cls;
39495             }
39496
39497             me.setWidth(target.width);
39498
39499             if (me.anchor) {
39500                 me.constrainPosition = false;
39501             } else if (target.align) { 
39502                 xy = me.el.getAlignToXY(target.el, target.align);
39503                 me.constrainPosition = false;
39504             }else{
39505                 me.constrainPosition = true;
39506             }
39507         }
39508         me.callParent([xy]);
39509     },
39510
39511     
39512     hide: function(){
39513         delete this.activeTarget;
39514         this.callParent();
39515     }
39516 });
39517
39518
39519 Ext.define('Ext.tip.QuickTipManager', function() {
39520     var tip,
39521         disabled = false;
39522
39523     return {
39524         requires: ['Ext.tip.QuickTip'],
39525         singleton: true,
39526         alternateClassName: 'Ext.QuickTips',
39527
39528         
39529         init : function (autoRender, config) {
39530             if (!tip) {
39531                 if (!Ext.isReady) {
39532                     Ext.onReady(function(){
39533                         Ext.tip.QuickTipManager.init(autoRender);
39534                     });
39535                     return;
39536                 }
39537
39538                 var tipConfig = Ext.apply({ disabled: disabled }, config),
39539                     className = tipConfig.className,
39540                     xtype = tipConfig.xtype;
39541
39542                 if (className) {
39543                     delete tipConfig.className;
39544                 } else if (xtype) {
39545                     className = 'widget.' + xtype;
39546                     delete tipConfig.xtype;
39547                 }
39548
39549                 if (autoRender !== false) {
39550                     tipConfig.renderTo = document.body;
39551
39552                 }
39553
39554                 tip = Ext.create(className || 'Ext.tip.QuickTip', tipConfig);
39555             }
39556         },
39557
39558         
39559         destroy: function() {
39560             if (tip) {
39561                 var undef;
39562                 tip.destroy();
39563                 tip = undef;
39564             }
39565         },
39566
39567         
39568         ddDisable : function(){
39569             
39570             if(tip && !disabled){
39571                 tip.disable();
39572             }
39573         },
39574
39575         
39576         ddEnable : function(){
39577             
39578             if(tip && !disabled){
39579                 tip.enable();
39580             }
39581         },
39582
39583         
39584         enable : function(){
39585             if(tip){
39586                 tip.enable();
39587             }
39588             disabled = false;
39589         },
39590
39591         
39592         disable : function(){
39593             if(tip){
39594                 tip.disable();
39595             }
39596             disabled = true;
39597         },
39598
39599         
39600         isEnabled : function(){
39601             return tip !== undefined && !tip.disabled;
39602         },
39603
39604         
39605         getQuickTip : function(){
39606             return tip;
39607         },
39608
39609         
39610         register : function(){
39611             tip.register.apply(tip, arguments);
39612         },
39613
39614         
39615         unregister : function(){
39616             tip.unregister.apply(tip, arguments);
39617         },
39618
39619         
39620         tips : function(){
39621             tip.register.apply(tip, arguments);
39622         }
39623     };
39624 }());
39625
39626 Ext.define('Ext.app.Application', {
39627     extend: 'Ext.app.Controller',
39628
39629     requires: [
39630         'Ext.ModelManager',
39631         'Ext.data.Model',
39632         'Ext.data.StoreManager',
39633         'Ext.tip.QuickTipManager',
39634         'Ext.ComponentManager',
39635         'Ext.app.EventBus'
39636     ],
39637
39638     
39639
39640     
39641     scope: undefined,
39642
39643     
39644     enableQuickTips: true,
39645
39646     
39647
39648     
39649     appFolder: 'app',
39650
39651     
39652     autoCreateViewport: false,
39653
39654     
39655     constructor: function(config) {
39656         config = config || {};
39657         Ext.apply(this, config);
39658
39659         var requires = config.requires || [];
39660
39661         Ext.Loader.setPath(this.name, this.appFolder);
39662
39663         if (this.paths) {
39664             Ext.Object.each(this.paths, function(key, value) {
39665                 Ext.Loader.setPath(key, value);
39666             });
39667         }
39668
39669         this.callParent(arguments);
39670
39671         this.eventbus = Ext.create('Ext.app.EventBus');
39672
39673         var controllers = Ext.Array.from(this.controllers),
39674             ln = controllers && controllers.length,
39675             i, controller;
39676
39677         this.controllers = Ext.create('Ext.util.MixedCollection');
39678
39679         if (this.autoCreateViewport) {
39680             requires.push(this.getModuleClassName('Viewport', 'view'));
39681         }
39682
39683         for (i = 0; i < ln; i++) {
39684             requires.push(this.getModuleClassName(controllers[i], 'controller'));
39685         }
39686
39687         Ext.require(requires);
39688
39689         Ext.onReady(function() {
39690             for (i = 0; i < ln; i++) {
39691                 controller = this.getController(controllers[i]);
39692                 controller.init(this);
39693             }
39694
39695             this.onBeforeLaunch.call(this);
39696         }, this);
39697     },
39698
39699     control: function(selectors, listeners, controller) {
39700         this.eventbus.control(selectors, listeners, controller);
39701     },
39702
39703     
39704     launch: Ext.emptyFn,
39705
39706     
39707     onBeforeLaunch: function() {
39708         if (this.enableQuickTips) {
39709             Ext.tip.QuickTipManager.init();
39710         }
39711
39712         if (this.autoCreateViewport) {
39713             this.getView('Viewport').create();
39714         }
39715
39716         this.launch.call(this.scope || this);
39717         this.launched = true;
39718         this.fireEvent('launch', this);
39719
39720         this.controllers.each(function(controller) {
39721             controller.onLaunch(this);
39722         }, this);
39723     },
39724
39725     getModuleClassName: function(name, type) {
39726         var namespace = Ext.Loader.getPrefix(name);
39727
39728         if (namespace.length > 0 && namespace !== name) {
39729             return name;
39730         }
39731
39732         return this.name + '.' + type + '.' + name;
39733     },
39734
39735     getController: function(name) {
39736         var controller = this.controllers.get(name);
39737
39738         if (!controller) {
39739             controller = Ext.create(this.getModuleClassName(name, 'controller'), {
39740                 application: this,
39741                 id: name
39742             });
39743
39744             this.controllers.add(controller);
39745         }
39746
39747         return controller;
39748     },
39749
39750     getStore: function(name) {
39751         var store = Ext.StoreManager.get(name);
39752
39753         if (!store) {
39754             store = Ext.create(this.getModuleClassName(name, 'store'), {
39755                 storeId: name
39756             });
39757         }
39758
39759         return store;
39760     },
39761
39762     getModel: function(model) {
39763         model = this.getModuleClassName(model, 'model');
39764
39765         return Ext.ModelManager.getModel(model);
39766     },
39767
39768     getView: function(view) {
39769         view = this.getModuleClassName(view, 'view');
39770
39771         return Ext.ClassManager.get(view);
39772     }
39773 });
39774
39775
39776 Ext.define('Ext.chart.Callout', {
39777
39778     
39779
39780     
39781
39782     constructor: function(config) {
39783         if (config.callouts) {
39784             config.callouts.styles = Ext.applyIf(config.callouts.styles || {}, {
39785                 color: "#000",
39786                 font: "11px Helvetica, sans-serif"
39787             });
39788             this.callouts = Ext.apply(this.callouts || {}, config.callouts);
39789             this.calloutsArray = [];
39790         }
39791     },
39792
39793     renderCallouts: function() {
39794         if (!this.callouts) {
39795             return;
39796         }
39797
39798         var me = this,
39799             items = me.items,
39800             animate = me.chart.animate,
39801             config = me.callouts,
39802             styles = config.styles,
39803             group = me.calloutsArray,
39804             store = me.chart.store,
39805             len = store.getCount(),
39806             ratio = items.length / len,
39807             previouslyPlacedCallouts = [],
39808             i,
39809             count,
39810             j,
39811             p;
39812             
39813         for (i = 0, count = 0; i < len; i++) {
39814             for (j = 0; j < ratio; j++) {
39815                 var item = items[count],
39816                     label = group[count],
39817                     storeItem = store.getAt(i),
39818                     display;
39819                 
39820                 display = config.filter(storeItem);
39821                 
39822                 if (!display && !label) {
39823                     count++;
39824                     continue;               
39825                 }
39826                 
39827                 if (!label) {
39828                     group[count] = label = me.onCreateCallout(storeItem, item, i, display, j, count);
39829                 }
39830                 for (p in label) {
39831                     if (label[p] && label[p].setAttributes) {
39832                         label[p].setAttributes(styles, true);
39833                     }
39834                 }
39835                 if (!display) {
39836                     for (p in label) {
39837                         if (label[p]) {
39838                             if (label[p].setAttributes) {
39839                                 label[p].setAttributes({
39840                                     hidden: true
39841                                 }, true);
39842                             } else if(label[p].setVisible) {
39843                                 label[p].setVisible(false);
39844                             }
39845                         }
39846                     }
39847                 }
39848                 config.renderer(label, storeItem);
39849                 me.onPlaceCallout(label, storeItem, item, i, display, animate,
39850                                   j, count, previouslyPlacedCallouts);
39851                 previouslyPlacedCallouts.push(label);
39852                 count++;
39853             }
39854         }
39855         this.hideCallouts(count);
39856     },
39857
39858     onCreateCallout: function(storeItem, item, i, display) {
39859         var me = this,
39860             group = me.calloutsGroup,
39861             config = me.callouts,
39862             styles = config.styles,
39863             width = styles.width,
39864             height = styles.height,
39865             chart = me.chart,
39866             surface = chart.surface,
39867             calloutObj = {
39868                 
39869                 
39870                 lines: false
39871             };
39872
39873         calloutObj.lines = surface.add(Ext.apply({},
39874         {
39875             type: 'path',
39876             path: 'M0,0',
39877             stroke: me.getLegendColor() || '#555'
39878         },
39879         styles));
39880
39881         if (config.items) {
39882             calloutObj.panel = Ext.create('widget.panel', {
39883                 style: "position: absolute;",    
39884                 width: width,
39885                 height: height,
39886                 items: config.items,
39887                 renderTo: chart.el
39888             });
39889         }
39890
39891         return calloutObj;
39892     },
39893
39894     hideCallouts: function(index) {
39895         var calloutsArray = this.calloutsArray,
39896             len = calloutsArray.length,
39897             co,
39898             p;
39899         while (len-->index) {
39900             co = calloutsArray[len];
39901             for (p in co) {
39902                 if (co[p]) {
39903                     co[p].hide(true);
39904                 }
39905             }
39906         }
39907     }
39908 });
39909
39910
39911 Ext.define('Ext.draw.CompositeSprite', {
39912
39913     
39914
39915     extend: 'Ext.util.MixedCollection',
39916     mixins: {
39917         animate: 'Ext.util.Animate'
39918     },
39919
39920     
39921     isCompositeSprite: true,
39922     constructor: function(config) {
39923         var me = this;
39924         
39925         config = config || {};
39926         Ext.apply(me, config);
39927
39928         me.addEvents(
39929             'mousedown',
39930             'mouseup',
39931             'mouseover',
39932             'mouseout',
39933             'click'
39934         );
39935         me.id = Ext.id(null, 'ext-sprite-group-');
39936         me.callParent();
39937     },
39938
39939     
39940     onClick: function(e) {
39941         this.fireEvent('click', e);
39942     },
39943
39944     
39945     onMouseUp: function(e) {
39946         this.fireEvent('mouseup', e);
39947     },
39948
39949     
39950     onMouseDown: function(e) {
39951         this.fireEvent('mousedown', e);
39952     },
39953
39954     
39955     onMouseOver: function(e) {
39956         this.fireEvent('mouseover', e);
39957     },
39958
39959     
39960     onMouseOut: function(e) {
39961         this.fireEvent('mouseout', e);
39962     },
39963
39964     attachEvents: function(o) {
39965         var me = this;
39966         
39967         o.on({
39968             scope: me,
39969             mousedown: me.onMouseDown,
39970             mouseup: me.onMouseUp,
39971             mouseover: me.onMouseOver,
39972             mouseout: me.onMouseOut,
39973             click: me.onClick
39974         });
39975     },
39976
39977     
39978     add: function(key, o) {
39979         var result = this.callParent(arguments);
39980         this.attachEvents(result);
39981         return result;
39982     },
39983
39984     insert: function(index, key, o) {
39985         return this.callParent(arguments);
39986     },
39987
39988     
39989     remove: function(o) {
39990         var me = this;
39991         
39992         o.un({
39993             scope: me,
39994             mousedown: me.onMouseDown,
39995             mouseup: me.onMouseUp,
39996             mouseover: me.onMouseOver,
39997             mouseout: me.onMouseOut,
39998             click: me.onClick
39999         });
40000         return me.callParent(arguments);
40001     },
40002     
40003     
40004     getBBox: function() {
40005         var i = 0,
40006             sprite,
40007             bb,
40008             items = this.items,
40009             len = this.length,
40010             infinity = Infinity,
40011             minX = infinity,
40012             maxHeight = -infinity,
40013             minY = infinity,
40014             maxWidth = -infinity,
40015             maxWidthBBox, maxHeightBBox;
40016         
40017         for (; i < len; i++) {
40018             sprite = items[i];
40019             if (sprite.el) {
40020                 bb = sprite.getBBox();
40021                 minX = Math.min(minX, bb.x);
40022                 minY = Math.min(minY, bb.y);
40023                 maxHeight = Math.max(maxHeight, bb.height + bb.y);
40024                 maxWidth = Math.max(maxWidth, bb.width + bb.x);
40025             }
40026         }
40027         
40028         return {
40029             x: minX,
40030             y: minY,
40031             height: maxHeight - minY,
40032             width: maxWidth - minX
40033         };
40034     },
40035
40036     
40037     setAttributes: function(attrs, redraw) {
40038         var i = 0,
40039             items = this.items,
40040             len = this.length;
40041             
40042         for (; i < len; i++) {
40043             items[i].setAttributes(attrs, redraw);
40044         }
40045         return this;
40046     },
40047
40048     
40049     hide: function(redraw) {
40050         var i = 0,
40051             items = this.items,
40052             len = this.length;
40053             
40054         for (; i < len; i++) {
40055             items[i].hide(redraw);
40056         }
40057         return this;
40058     },
40059
40060     
40061     show: function(redraw) {
40062         var i = 0,
40063             items = this.items,
40064             len = this.length;
40065             
40066         for (; i < len; i++) {
40067             items[i].show(redraw);
40068         }
40069         return this;
40070     },
40071
40072     redraw: function() {
40073         var me = this,
40074             i = 0,
40075             items = me.items,
40076             surface = me.getSurface(),
40077             len = me.length;
40078         
40079         if (surface) {
40080             for (; i < len; i++) {
40081                 surface.renderItem(items[i]);
40082             }
40083         }
40084         return me;
40085     },
40086
40087     setStyle: function(obj) {
40088         var i = 0,
40089             items = this.items,
40090             len = this.length,
40091             item, el;
40092             
40093         for (; i < len; i++) {
40094             item = items[i];
40095             el = item.el;
40096             if (el) {
40097                 el.setStyle(obj);
40098             }
40099         }
40100     },
40101
40102     addCls: function(obj) {
40103         var i = 0,
40104             items = this.items,
40105             surface = this.getSurface(),
40106             len = this.length;
40107         
40108         if (surface) {
40109             for (; i < len; i++) {
40110                 surface.addCls(items[i], obj);
40111             }
40112         }
40113     },
40114
40115     removeCls: function(obj) {
40116         var i = 0,
40117             items = this.items,
40118             surface = this.getSurface(),
40119             len = this.length;
40120         
40121         if (surface) {
40122             for (; i < len; i++) {
40123                 surface.removeCls(items[i], obj);
40124             }
40125         }
40126     },
40127     
40128     
40129     getSurface: function(){
40130         var first = this.first();
40131         if (first) {
40132             return first.surface;
40133         }
40134         return null;
40135     },
40136     
40137     
40138     destroy: function(){
40139         var me = this,
40140             surface = me.getSurface(),
40141             item;
40142             
40143         if (surface) {
40144             while (me.getCount() > 0) {
40145                 item = me.first();
40146                 me.remove(item);
40147                 surface.remove(item);
40148             }
40149         }
40150         me.clearListeners();
40151     }
40152 });
40153
40154
40155
40156 Ext.define('Ext.layout.component.Auto', {
40157
40158     
40159
40160     alias: 'layout.autocomponent',
40161
40162     extend: 'Ext.layout.component.Component',
40163
40164     
40165
40166     type: 'autocomponent',
40167
40168     onLayout : function(width, height) {
40169         this.setTargetSize(width, height);
40170     }
40171 });
40172
40173 Ext.define('Ext.chart.theme.Theme', {
40174
40175     
40176
40177     requires: ['Ext.draw.Color'],
40178
40179     
40180
40181     theme: 'Base',
40182     themeAttrs: false,
40183     
40184     initTheme: function(theme) {
40185         var me = this,
40186             themes = Ext.chart.theme,
40187             key, gradients;
40188         if (theme) {
40189             theme = theme.split(':');
40190             for (key in themes) {
40191                 if (key == theme[0]) {
40192                     gradients = theme[1] == 'gradients';
40193                     me.themeAttrs = new themes[key]({
40194                         useGradients: gradients
40195                     });
40196                     if (gradients) {
40197                         me.gradients = me.themeAttrs.gradients;
40198                     }
40199                     if (me.themeAttrs.background) {
40200                         me.background = me.themeAttrs.background;
40201                     }
40202                     return;
40203                 }
40204             }
40205         }
40206     }
40207 }, 
40208
40209 function() {
40210    
40211
40212 (function() {
40213     Ext.chart.theme = function(config, base) {
40214         config = config || {};
40215         var i = 0, l, colors, color,
40216             seriesThemes, markerThemes,
40217             seriesTheme, markerTheme, 
40218             key, gradients = [],
40219             midColor, midL;
40220         
40221         if (config.baseColor) {
40222             midColor = Ext.draw.Color.fromString(config.baseColor);
40223             midL = midColor.getHSL()[2];
40224             if (midL < 0.15) {
40225                 midColor = midColor.getLighter(0.3);
40226             } else if (midL < 0.3) {
40227                 midColor = midColor.getLighter(0.15);
40228             } else if (midL > 0.85) {
40229                 midColor = midColor.getDarker(0.3);
40230             } else if (midL > 0.7) {
40231                 midColor = midColor.getDarker(0.15);
40232             }
40233             config.colors = [ midColor.getDarker(0.3).toString(),
40234                               midColor.getDarker(0.15).toString(),
40235                               midColor.toString(),
40236                               midColor.getLighter(0.15).toString(),
40237                               midColor.getLighter(0.3).toString()];
40238
40239             delete config.baseColor;
40240         }
40241         if (config.colors) {
40242             colors = config.colors.slice();
40243             markerThemes = base.markerThemes;
40244             seriesThemes = base.seriesThemes;
40245             l = colors.length;
40246             base.colors = colors;
40247             for (; i < l; i++) {
40248                 color = colors[i];
40249                 markerTheme = markerThemes[i] || {};
40250                 seriesTheme = seriesThemes[i] || {};
40251                 markerTheme.fill = seriesTheme.fill = markerTheme.stroke = seriesTheme.stroke = color;
40252                 markerThemes[i] = markerTheme;
40253                 seriesThemes[i] = seriesTheme;
40254             }
40255             base.markerThemes = markerThemes.slice(0, l);
40256             base.seriesThemes = seriesThemes.slice(0, l);
40257         
40258         }
40259         for (key in base) {
40260             if (key in config) {
40261                 if (Ext.isObject(config[key]) && Ext.isObject(base[key])) {
40262                     Ext.apply(base[key], config[key]);
40263                 } else {
40264                     base[key] = config[key];
40265                 }
40266             }
40267         }
40268         if (config.useGradients) {
40269             colors = base.colors || (function () {
40270                 var ans = [];
40271                 for (i = 0, seriesThemes = base.seriesThemes, l = seriesThemes.length; i < l; i++) {
40272                     ans.push(seriesThemes[i].fill || seriesThemes[i].stroke);
40273                 }
40274                 return ans;
40275             })();
40276             for (i = 0, l = colors.length; i < l; i++) {
40277                 midColor = Ext.draw.Color.fromString(colors[i]);
40278                 if (midColor) {
40279                     color = midColor.getDarker(0.1).toString();
40280                     midColor = midColor.toString();
40281                     key = 'theme-' + midColor.substr(1) + '-' + color.substr(1);
40282                     gradients.push({
40283                         id: key,
40284                         angle: 45,
40285                         stops: {
40286                             0: {
40287                                 color: midColor.toString()
40288                             },
40289                             100: {
40290                                 color: color.toString()
40291                             }
40292                         }
40293                     });
40294                     colors[i] = 'url(#' + key + ')'; 
40295                 }
40296             }
40297             base.gradients = gradients;
40298             base.colors = colors;
40299         }
40300         
40301         Ext.apply(this, base);
40302     };
40303 })();
40304 });
40305
40306
40307 Ext.define('Ext.chart.Mask', {
40308     require: ['Ext.chart.MaskLayer'],
40309     
40310     constructor: function(config) {
40311         var me = this;
40312
40313         me.addEvents('select');
40314
40315         if (config) {
40316             Ext.apply(me, config);
40317         }
40318         if (me.mask) {
40319             me.on('afterrender', function() {
40320                 
40321                 var comp = Ext.create('Ext.chart.MaskLayer', {
40322                     renderTo: me.el
40323                 });
40324                 comp.el.on({
40325                     'mousemove': function(e) {
40326                         me.onMouseMove(e);
40327                     },
40328                     'mouseup': function(e) {
40329                         me.resized(e);
40330                     }
40331                 });
40332                 
40333                 var resizeHandler = Ext.create('Ext.resizer.Resizer', {
40334                     el: comp.el,
40335                     handles: 'all',
40336                     pinned: true
40337                 });
40338                 resizeHandler.on({
40339                     'resize': function(e) {
40340                         me.resized(e);    
40341                     }    
40342                 });
40343                 comp.initDraggable();
40344                 me.maskType = me.mask;
40345                 me.mask = comp;
40346                 me.maskSprite = me.surface.add({
40347                     type: 'path',
40348                     path: ['M', 0, 0],
40349                     zIndex: 1001,
40350                     opacity: 0.7,
40351                     hidden: true,
40352                     stroke: '#444'
40353                 });
40354             }, me, { single: true });
40355         }
40356     },
40357     
40358     resized: function(e) {
40359         var me = this,
40360             bbox = me.bbox || me.chartBBox,
40361             x = bbox.x,
40362             y = bbox.y,
40363             width = bbox.width,
40364             height = bbox.height,
40365             box = me.mask.getBox(true),
40366             max = Math.max,
40367             min = Math.min,
40368             staticX = box.x - x,
40369             staticY = box.y - y;
40370         
40371         staticX = max(staticX, x);
40372         staticY = max(staticY, y);
40373         staticX = min(staticX, width);
40374         staticY = min(staticY, height);
40375         box.x = staticX;
40376         box.y = staticY;
40377         me.fireEvent('select', me, box);
40378     },
40379
40380     onMouseUp: function(e) {
40381         var me = this,
40382             bbox = me.bbox || me.chartBBox,
40383             sel = me.maskSelection;
40384         me.maskMouseDown = false;
40385         me.mouseDown = false;
40386         if (me.mouseMoved) {
40387             me.onMouseMove(e);
40388             me.mouseMoved = false;
40389             me.fireEvent('select', me, {
40390                 x: sel.x - bbox.x,
40391                 y: sel.y - bbox.y,
40392                 width: sel.width,
40393                 height: sel.height
40394             });
40395         }
40396     },
40397
40398     onMouseDown: function(e) {
40399         var me = this;
40400         me.mouseDown = true;
40401         me.mouseMoved = false;
40402         me.maskMouseDown = {
40403             x: e.getPageX() - me.el.getX(),
40404             y: e.getPageY() - me.el.getY()
40405         };
40406     },
40407
40408     onMouseMove: function(e) {
40409         var me = this,
40410             mask = me.maskType,
40411             bbox = me.bbox || me.chartBBox,
40412             x = bbox.x,
40413             y = bbox.y,
40414             math = Math,
40415             floor = math.floor,
40416             abs = math.abs,
40417             min = math.min,
40418             max = math.max,
40419             height = floor(y + bbox.height),
40420             width = floor(x + bbox.width),
40421             posX = e.getPageX(),
40422             posY = e.getPageY(),
40423             staticX = posX - me.el.getX(),
40424             staticY = posY - me.el.getY(),
40425             maskMouseDown = me.maskMouseDown,
40426             path;
40427         
40428         me.mouseMoved = me.mouseDown;
40429         staticX = max(staticX, x);
40430         staticY = max(staticY, y);
40431         staticX = min(staticX, width);
40432         staticY = min(staticY, height);
40433         if (maskMouseDown && me.mouseDown) {
40434             if (mask == 'horizontal') {
40435                 staticY = y;
40436                 maskMouseDown.y = height;
40437                 posY = me.el.getY() + bbox.height + me.insetPadding;
40438             }
40439             else if (mask == 'vertical') {
40440                 staticX = x;
40441                 maskMouseDown.x = width;
40442             }
40443             width = maskMouseDown.x - staticX;
40444             height = maskMouseDown.y - staticY;
40445             path = ['M', staticX, staticY, 'l', width, 0, 0, height, -width, 0, 'z'];
40446             me.maskSelection = {
40447                 x: width > 0 ? staticX : staticX + width,
40448                 y: height > 0 ? staticY : staticY + height,
40449                 width: abs(width),
40450                 height: abs(height)
40451             };
40452             me.mask.updateBox(me.maskSelection);
40453             me.mask.show();
40454             me.maskSprite.setAttributes({
40455                 hidden: true    
40456             }, true);
40457         }
40458         else {
40459             if (mask == 'horizontal') {
40460                 path = ['M', staticX, y, 'L', staticX, height];
40461             }
40462             else if (mask == 'vertical') {
40463                 path = ['M', x, staticY, 'L', width, staticY];
40464             }
40465             else {
40466                 path = ['M', staticX, y, 'L', staticX, height, 'M', x, staticY, 'L', width, staticY];
40467             }
40468             me.maskSprite.setAttributes({
40469                 path: path,
40470                 fill: me.maskMouseDown ? me.maskSprite.stroke : false,
40471                 'stroke-width': mask === true ? 1 : 3,
40472                 hidden: false
40473             }, true);
40474         }
40475     },
40476
40477     onMouseLeave: function(e) {
40478         var me = this;
40479         me.mouseMoved = false;
40480         me.mouseDown = false;
40481         me.maskMouseDown = false;
40482         me.mask.hide();
40483         me.maskSprite.hide(true);
40484     }
40485 });
40486     
40487
40488 Ext.define('Ext.chart.Navigation', {
40489
40490     constructor: function() {
40491         this.originalStore = this.store;
40492     },
40493
40494     
40495     setZoom: function(zoomConfig) {
40496         var me = this,
40497             axes = me.axes,
40498             bbox = me.chartBBox,
40499             xScale = 1 / bbox.width,
40500             yScale = 1 / bbox.height,
40501             zoomer = {
40502                 x : zoomConfig.x * xScale,
40503                 y : zoomConfig.y * yScale,
40504                 width : zoomConfig.width * xScale,
40505                 height : zoomConfig.height * yScale
40506             };
40507         axes.each(function(axis) {
40508             var ends = axis.calcEnds();
40509             if (axis.position == 'bottom' || axis.position == 'top') {
40510                 var from = (ends.to - ends.from) * zoomer.x + ends.from,
40511                     to = (ends.to - ends.from) * zoomer.width + from;
40512                 axis.minimum = from;
40513                 axis.maximum = to;
40514             } else {
40515                 var to = (ends.to - ends.from) * (1 - zoomer.y) + ends.from,
40516                     from = to - (ends.to - ends.from) * zoomer.height;
40517                 axis.minimum = from;
40518                 axis.maximum = to;
40519             }
40520         });
40521         me.redraw(false);
40522     },
40523
40524     
40525     restoreZoom: function() {
40526         this.store = this.substore = this.originalStore;
40527         this.redraw(true);
40528     }
40529
40530 });
40531
40532
40533 Ext.define('Ext.chart.Shape', {
40534
40535     
40536
40537     singleton: true,
40538
40539     
40540
40541     circle: function (surface, opts) {
40542         return surface.add(Ext.apply({
40543             type: 'circle',
40544             x: opts.x,
40545             y: opts.y,
40546             stroke: null,
40547             radius: opts.radius
40548         }, opts));
40549     },
40550     line: function (surface, opts) {
40551         return surface.add(Ext.apply({
40552             type: 'rect',
40553             x: opts.x - opts.radius,
40554             y: opts.y - opts.radius,
40555             height: 2 * opts.radius,
40556             width: 2 * opts.radius / 5
40557         }, opts));
40558     },
40559     square: function (surface, opts) {
40560         return surface.add(Ext.applyIf({
40561             type: 'rect',
40562             x: opts.x - opts.radius,
40563             y: opts.y - opts.radius,
40564             height: 2 * opts.radius,
40565             width: 2 * opts.radius,
40566             radius: null
40567         }, opts));
40568     },
40569     triangle: function (surface, opts) {
40570         opts.radius *= 1.75;
40571         return surface.add(Ext.apply({
40572             type: 'path',
40573             stroke: null,
40574             path: "M".concat(opts.x, ",", opts.y, "m0-", opts.radius * 0.58, "l", opts.radius * 0.5, ",", opts.radius * 0.87, "-", opts.radius, ",0z")
40575         }, opts));
40576     },
40577     diamond: function (surface, opts) {
40578         var r = opts.radius;
40579         r *= 1.5;
40580         return surface.add(Ext.apply({
40581             type: 'path',
40582             stroke: null,
40583             path: ["M", opts.x, opts.y - r, "l", r, r, -r, r, -r, -r, r, -r, "z"]
40584         }, opts));
40585     },
40586     cross: function (surface, opts) {
40587         var r = opts.radius;
40588         r = r / 1.7;
40589         return surface.add(Ext.apply({
40590             type: 'path',
40591             stroke: null,
40592             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"])
40593         }, opts));
40594     },
40595     plus: function (surface, opts) {
40596         var r = opts.radius / 1.3;
40597         return surface.add(Ext.apply({
40598             type: 'path',
40599             stroke: null,
40600             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"])
40601         }, opts));
40602     },
40603     arrow: function (surface, opts) {
40604         var r = opts.radius;
40605         return surface.add(Ext.apply({
40606             type: 'path',
40607             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")
40608         }, opts));
40609     },
40610     drop: function (surface, x, y, text, size, angle) {
40611         size = size || 30;
40612         angle = angle || 0;
40613         surface.add({
40614             type: 'path',
40615             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'],
40616             fill: '#000',
40617             stroke: 'none',
40618             rotate: {
40619                 degrees: 22.5 - angle,
40620                 x: x,
40621                 y: y
40622             }
40623         });
40624         angle = (angle + 90) * Math.PI / 180;
40625         surface.add({
40626             type: 'text',
40627             x: x + size * Math.sin(angle) - 10, 
40628             y: y + size * Math.cos(angle) + 5,
40629             text:  text,
40630             'font-size': size * 12 / 40,
40631             stroke: 'none',
40632             fill: '#fff'
40633         });
40634     }
40635 });
40636
40637 Ext.define('Ext.draw.Surface', {
40638
40639     
40640
40641     mixins: {
40642         observable: 'Ext.util.Observable'
40643     },
40644
40645     requires: ['Ext.draw.CompositeSprite'],
40646     uses: ['Ext.draw.engine.Svg', 'Ext.draw.engine.Vml'],
40647
40648     separatorRe: /[, ]+/,
40649
40650     statics: {
40651         
40652         create: function(config, enginePriority) {
40653             enginePriority = enginePriority || ['Svg', 'Vml'];
40654
40655             var i = 0,
40656                 len = enginePriority.length,
40657                 surfaceClass;
40658
40659             for (; i < len; i++) {
40660                 if (Ext.supports[enginePriority[i]]) {
40661                     return Ext.create('Ext.draw.engine.' + enginePriority[i], config);
40662                 }
40663             }
40664             return false;
40665         }
40666     },
40667
40668     
40669
40670     
40671     availableAttrs: {
40672         blur: 0,
40673         "clip-rect": "0 0 1e9 1e9",
40674         cursor: "default",
40675         cx: 0,
40676         cy: 0,
40677         'dominant-baseline': 'auto',
40678         fill: "none",
40679         "fill-opacity": 1,
40680         font: '10px "Arial"',
40681         "font-family": '"Arial"',
40682         "font-size": "10",
40683         "font-style": "normal",
40684         "font-weight": 400,
40685         gradient: "",
40686         height: 0,
40687         hidden: false,
40688         href: "http://sencha.com/",
40689         opacity: 1,
40690         path: "M0,0",
40691         radius: 0,
40692         rx: 0,
40693         ry: 0,
40694         scale: "1 1",
40695         src: "",
40696         stroke: "#000",
40697         "stroke-dasharray": "",
40698         "stroke-linecap": "butt",
40699         "stroke-linejoin": "butt",
40700         "stroke-miterlimit": 0,
40701         "stroke-opacity": 1,
40702         "stroke-width": 1,
40703         target: "_blank",
40704         text: "",
40705         "text-anchor": "middle",
40706         title: "Ext Draw",
40707         width: 0,
40708         x: 0,
40709         y: 0,
40710         zIndex: 0
40711     },
40712
40713     
40714     
40715
40716     container: undefined,
40717     height: 352,
40718     width: 512,
40719     x: 0,
40720     y: 0,
40721
40722     
40723     orderSpritesByZIndex: true,
40724
40725
40726     
40727     constructor: function(config) {
40728         var me = this;
40729         config = config || {};
40730         Ext.apply(me, config);
40731
40732         me.domRef = Ext.getDoc().dom;
40733
40734         me.customAttributes = {};
40735
40736         me.addEvents(
40737             'mousedown',
40738             'mouseup',
40739             'mouseover',
40740             'mouseout',
40741             'mousemove',
40742             'mouseenter',
40743             'mouseleave',
40744             'click'
40745         );
40746
40747         me.mixins.observable.constructor.call(me);
40748
40749         me.getId();
40750         me.initGradients();
40751         me.initItems();
40752         if (me.renderTo) {
40753             me.render(me.renderTo);
40754             delete me.renderTo;
40755         }
40756         me.initBackground(config.background);
40757     },
40758
40759     
40760     
40761     initSurface: Ext.emptyFn,
40762
40763     
40764     
40765     renderItem: Ext.emptyFn,
40766
40767     
40768     renderItems: Ext.emptyFn,
40769
40770     
40771     setViewBox: function (x, y, width, height) {
40772         if (isFinite(x) && isFinite(y) && isFinite(width) && isFinite(height)) {
40773             this.viewBox = {x: x, y: y, width: width, height: height};
40774             this.applyViewBox();
40775         }
40776     },
40777
40778     
40779     addCls: Ext.emptyFn,
40780
40781     
40782     removeCls: Ext.emptyFn,
40783
40784     
40785     setStyle: Ext.emptyFn,
40786
40787     
40788     initGradients: function() {
40789         var gradients = this.gradients;
40790         if (gradients) {
40791             Ext.each(gradients, this.addGradient, this);
40792         }
40793     },
40794
40795     
40796     initItems: function() {
40797         var items = this.items;
40798         this.items = Ext.create('Ext.draw.CompositeSprite');
40799         this.groups = Ext.create('Ext.draw.CompositeSprite');
40800         if (items) {
40801             this.add(items);
40802         }
40803     },
40804
40805     
40806     initBackground: function(config) {
40807         var me = this,
40808             width = me.width,
40809             height = me.height,
40810             gradientId, gradient, backgroundSprite;
40811         if (config) {
40812             if (config.gradient) {
40813                 gradient = config.gradient;
40814                 gradientId = gradient.id;
40815                 me.addGradient(gradient);
40816                 me.background = me.add({
40817                     type: 'rect',
40818                     x: 0,
40819                     y: 0,
40820                     width: width,
40821                     height: height,
40822                     fill: 'url(#' + gradientId + ')'
40823                 });
40824             } else if (config.fill) {
40825                 me.background = me.add({
40826                     type: 'rect',
40827                     x: 0,
40828                     y: 0,
40829                     width: width,
40830                     height: height,
40831                     fill: config.fill
40832                 });
40833             } else if (config.image) {
40834                 me.background = me.add({
40835                     type: 'image',
40836                     x: 0,
40837                     y: 0,
40838                     width: width,
40839                     height: height,
40840                     src: config.image
40841                 });
40842             }
40843         }
40844     },
40845
40846     
40847     setSize: function(w, h) {
40848         if (this.background) {
40849             this.background.setAttributes({
40850                 width: w,
40851                 height: h,
40852                 hidden: false
40853             }, true);
40854         }
40855         this.applyViewBox();
40856     },
40857
40858     
40859     scrubAttrs: function(sprite) {
40860         var i,
40861             attrs = {},
40862             exclude = {},
40863             sattr = sprite.attr;
40864         for (i in sattr) {
40865             
40866             if (this.translateAttrs.hasOwnProperty(i)) {
40867                 
40868                 attrs[this.translateAttrs[i]] = sattr[i];
40869                 exclude[this.translateAttrs[i]] = true;
40870             }
40871             else if (this.availableAttrs.hasOwnProperty(i) && !exclude[i]) {
40872                 
40873                 attrs[i] = sattr[i];
40874             }
40875         }
40876         return attrs;
40877     },
40878
40879     
40880     onClick: function(e) {
40881         this.processEvent('click', e);
40882     },
40883
40884     
40885     onMouseUp: function(e) {
40886         this.processEvent('mouseup', e);
40887     },
40888
40889     
40890     onMouseDown: function(e) {
40891         this.processEvent('mousedown', e);
40892     },
40893
40894     
40895     onMouseOver: function(e) {
40896         this.processEvent('mouseover', e);
40897     },
40898
40899     
40900     onMouseOut: function(e) {
40901         this.processEvent('mouseout', e);
40902     },
40903
40904     
40905     onMouseMove: function(e) {
40906         this.fireEvent('mousemove', e);
40907     },
40908
40909     
40910     onMouseEnter: Ext.emptyFn,
40911
40912     
40913     onMouseLeave: Ext.emptyFn,
40914
40915     
40916     addGradient: Ext.emptyFn,
40917
40918     
40919     add: function() {
40920         var args = Array.prototype.slice.call(arguments),
40921             sprite,
40922             index;
40923
40924         var hasMultipleArgs = args.length > 1;
40925         if (hasMultipleArgs || Ext.isArray(args[0])) {
40926             var items = hasMultipleArgs ? args : args[0],
40927                 results = [],
40928                 i, ln, item;
40929
40930             for (i = 0, ln = items.length; i < ln; i++) {
40931                 item = items[i];
40932                 item = this.add(item);
40933                 results.push(item);
40934             }
40935
40936             return results;
40937         }
40938         sprite = this.prepareItems(args[0], true)[0];
40939         this.insertByZIndex(sprite);
40940         this.onAdd(sprite);
40941         return sprite;
40942     },
40943
40944     
40945     insertByZIndex: function(sprite) {
40946         var me = this,
40947             sprites = me.items.items,
40948             len = sprites.length,
40949             ceil = Math.ceil,
40950             zIndex = sprite.attr.zIndex,
40951             idx = len,
40952             high = idx - 1,
40953             low = 0,
40954             otherZIndex;
40955
40956         if (me.orderSpritesByZIndex && len && zIndex < sprites[high].attr.zIndex) {
40957             
40958             while (low <= high) {
40959                 idx = ceil((low + high) / 2);
40960                 otherZIndex = sprites[idx].attr.zIndex;
40961                 if (otherZIndex > zIndex) {
40962                     high = idx - 1;
40963                 }
40964                 else if (otherZIndex < zIndex) {
40965                     low = idx + 1;
40966                 }
40967                 else {
40968                     break;
40969                 }
40970             }
40971             
40972             while (idx < len && sprites[idx].attr.zIndex <= zIndex) {
40973                 idx++;
40974             }
40975         }
40976
40977         me.items.insert(idx, sprite);
40978         return idx;
40979     },
40980
40981     onAdd: function(sprite) {
40982         var group = sprite.group,
40983             draggable = sprite.draggable,
40984             groups, ln, i;
40985         if (group) {
40986             groups = [].concat(group);
40987             ln = groups.length;
40988             for (i = 0; i < ln; i++) {
40989                 group = groups[i];
40990                 this.getGroup(group).add(sprite);
40991             }
40992             delete sprite.group;
40993         }
40994         if (draggable) {
40995             sprite.initDraggable();
40996         }
40997     },
40998
40999     
41000     remove: function(sprite, destroySprite) {
41001         if (sprite) {
41002             this.items.remove(sprite);
41003             this.groups.each(function(item) {
41004                 item.remove(sprite);
41005             });
41006             sprite.onRemove();
41007             if (destroySprite === true) {
41008                 sprite.destroy();
41009             }
41010         }
41011     },
41012
41013     
41014     removeAll: function(destroySprites) {
41015         var items = this.items.items,
41016             ln = items.length,
41017             i;
41018         for (i = ln - 1; i > -1; i--) {
41019             this.remove(items[i], destroySprites);
41020         }
41021     },
41022
41023     onRemove: Ext.emptyFn,
41024
41025     onDestroy: Ext.emptyFn,
41026
41027     
41028     applyViewBox: function() {
41029         var me = this,
41030             viewBox = me.viewBox,
41031             width = me.width,
41032             height = me.height,
41033             viewBoxX, viewBoxY, viewBoxWidth, viewBoxHeight,
41034             relativeHeight, relativeWidth, size;
41035
41036         if (viewBox && (width || height)) {
41037             viewBoxX = viewBox.x;
41038             viewBoxY = viewBox.y;
41039             viewBoxWidth = viewBox.width;
41040             viewBoxHeight = viewBox.height;
41041             relativeHeight = height / viewBoxHeight;
41042             relativeWidth = width / viewBoxWidth;
41043
41044             if (viewBoxWidth * relativeHeight < width) {
41045                 viewBoxX -= (width - viewBoxWidth * relativeHeight) / 2 / relativeHeight;
41046             }
41047             if (viewBoxHeight * relativeWidth < height) {
41048                 viewBoxY -= (height - viewBoxHeight * relativeWidth) / 2 / relativeWidth;
41049             }
41050
41051             size = 1 / Math.min(viewBoxWidth, relativeHeight);
41052
41053             me.viewBoxShift = {
41054                 dx: -viewBoxX,
41055                 dy: -viewBoxY,
41056                 scale: size
41057             };
41058         }
41059     },
41060
41061     transformToViewBox: function (x, y) {
41062         if (this.viewBoxShift) {
41063             var me = this, shift = me.viewBoxShift;
41064             return [x * shift.scale - shift.dx, y * shift.scale - shift.dy];
41065         } else {
41066             return [x, y];
41067         }
41068     },
41069
41070     
41071     applyTransformations: function(sprite) {
41072             sprite.bbox.transform = 0;
41073             this.transform(sprite);
41074
41075         var me = this,
41076             dirty = false,
41077             attr = sprite.attr;
41078
41079         if (attr.translation.x != null || attr.translation.y != null) {
41080             me.translate(sprite);
41081             dirty = true;
41082         }
41083         if (attr.scaling.x != null || attr.scaling.y != null) {
41084             me.scale(sprite);
41085             dirty = true;
41086         }
41087         if (attr.rotation.degrees != null) {
41088             me.rotate(sprite);
41089             dirty = true;
41090         }
41091         if (dirty) {
41092             sprite.bbox.transform = 0;
41093             this.transform(sprite);
41094             sprite.transformations = [];
41095         }
41096     },
41097
41098     
41099     rotate: function (sprite) {
41100         var bbox,
41101             deg = sprite.attr.rotation.degrees,
41102             centerX = sprite.attr.rotation.x,
41103             centerY = sprite.attr.rotation.y;
41104         if (!Ext.isNumber(centerX) || !Ext.isNumber(centerY)) {
41105             bbox = this.getBBox(sprite);
41106             centerX = !Ext.isNumber(centerX) ? bbox.x + bbox.width / 2 : centerX;
41107             centerY = !Ext.isNumber(centerY) ? bbox.y + bbox.height / 2 : centerY;
41108         }
41109         sprite.transformations.push({
41110             type: "rotate",
41111             degrees: deg,
41112             x: centerX,
41113             y: centerY
41114         });
41115     },
41116
41117     
41118     translate: function(sprite) {
41119         var x = sprite.attr.translation.x || 0,
41120             y = sprite.attr.translation.y || 0;
41121         sprite.transformations.push({
41122             type: "translate",
41123             x: x,
41124             y: y
41125         });
41126     },
41127
41128     
41129     scale: function(sprite) {
41130         var bbox,
41131             x = sprite.attr.scaling.x || 1,
41132             y = sprite.attr.scaling.y || 1,
41133             centerX = sprite.attr.scaling.centerX,
41134             centerY = sprite.attr.scaling.centerY;
41135
41136         if (!Ext.isNumber(centerX) || !Ext.isNumber(centerY)) {
41137             bbox = this.getBBox(sprite);
41138             centerX = !Ext.isNumber(centerX) ? bbox.x + bbox.width / 2 : centerX;
41139             centerY = !Ext.isNumber(centerY) ? bbox.y + bbox.height / 2 : centerY;
41140         }
41141         sprite.transformations.push({
41142             type: "scale",
41143             x: x,
41144             y: y,
41145             centerX: centerX,
41146             centerY: centerY
41147         });
41148     },
41149
41150     
41151     rectPath: function (x, y, w, h, r) {
41152         if (r) {
41153             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"]];
41154         }
41155         return [["M", x, y], ["l", w, 0], ["l", 0, h], ["l", -w, 0], ["z"]];
41156     },
41157
41158     
41159     ellipsePath: function (x, y, rx, ry) {
41160         if (ry == null) {
41161             ry = rx;
41162         }
41163         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"]];
41164     },
41165
41166     
41167     getPathpath: function (el) {
41168         return el.attr.path;
41169     },
41170
41171     
41172     getPathcircle: function (el) {
41173         var a = el.attr;
41174         return this.ellipsePath(a.x, a.y, a.radius, a.radius);
41175     },
41176
41177     
41178     getPathellipse: function (el) {
41179         var a = el.attr;
41180         return this.ellipsePath(a.x, a.y,
41181                                 a.radiusX || (a.width / 2) || 0,
41182                                 a.radiusY || (a.height / 2) || 0);
41183     },
41184
41185     
41186     getPathrect: function (el) {
41187         var a = el.attr;
41188         return this.rectPath(a.x, a.y, a.width, a.height, a.r);
41189     },
41190
41191     
41192     getPathimage: function (el) {
41193         var a = el.attr;
41194         return this.rectPath(a.x || 0, a.y || 0, a.width, a.height);
41195     },
41196
41197     
41198     getPathtext: function (el) {
41199         var bbox = this.getBBoxText(el);
41200         return this.rectPath(bbox.x, bbox.y, bbox.width, bbox.height);
41201     },
41202
41203     createGroup: function(id) {
41204         var group = this.groups.get(id);
41205         if (!group) {
41206             group = Ext.create('Ext.draw.CompositeSprite', {
41207                 surface: this
41208             });
41209             group.id = id || Ext.id(null, 'ext-surface-group-');
41210             this.groups.add(group);
41211         }
41212         return group;
41213     },
41214
41215     
41216     getGroup: function(id) {
41217         if (typeof id == "string") {
41218             var group = this.groups.get(id);
41219             if (!group) {
41220                 group = this.createGroup(id);
41221             }
41222         } else {
41223             group = id;
41224         }
41225         return group;
41226     },
41227
41228     
41229     prepareItems: function(items, applyDefaults) {
41230         items = [].concat(items);
41231         
41232         var item, i, ln;
41233         for (i = 0, ln = items.length; i < ln; i++) {
41234             item = items[i];
41235             if (!(item instanceof Ext.draw.Sprite)) {
41236                 
41237                 item.surface = this;
41238                 items[i] = this.createItem(item);
41239             } else {
41240                 item.surface = this;
41241             }
41242         }
41243         return items;
41244     },
41245
41246     
41247     setText: Ext.emptyFn,
41248
41249     //@private Creates an item and appends it to the surface. Called
41250
41251     
41252     createItem: Ext.emptyFn,
41253
41254     
41255     getId: function() {
41256         return this.id || (this.id = Ext.id(null, 'ext-surface-'));
41257     },
41258
41259     
41260     destroy: function() {
41261         delete this.domRef;
41262         this.removeAll();
41263     }
41264 });
41265
41266
41267 Ext.define('Ext.layout.component.Draw', {
41268
41269     
41270
41271     alias: 'layout.draw',
41272
41273     extend: 'Ext.layout.component.Auto',
41274
41275     
41276
41277     type: 'draw',
41278
41279     onLayout : function(width, height) {
41280         this.owner.surface.setSize(width, height);
41281         this.callParent(arguments);
41282     }
41283 });
41284
41285 Ext.define('Ext.draw.Component', {
41286
41287     
41288
41289     alias: 'widget.draw',
41290
41291     extend: 'Ext.Component',
41292
41293     requires: [
41294         'Ext.draw.Surface',
41295         'Ext.layout.component.Draw'
41296     ],
41297
41298     
41299
41300     
41301     enginePriority: ['Svg', 'Vml'],
41302
41303     baseCls: Ext.baseCSSPrefix + 'surface',
41304
41305     componentLayout: 'draw',
41306
41307     
41308     viewBox: true,
41309
41310     
41311     autoSize: false,
41312
41313     
41314     initComponent: function() {
41315         this.callParent(arguments);
41316
41317         this.addEvents(
41318             'mousedown',
41319             'mouseup',
41320             'mousemove',
41321             'mouseenter',
41322             'mouseleave',
41323             'click'
41324         );
41325     },
41326
41327     
41328     onRender: function() {
41329         var me = this,
41330             viewBox = me.viewBox,
41331             autoSize = me.autoSize,
41332             bbox, items, width, height, x, y;
41333         me.callParent(arguments);
41334
41335         if (me.createSurface() !== false) {
41336             items = me.surface.items;
41337
41338             if (viewBox || autoSize) {
41339                 bbox = items.getBBox();
41340                 width = bbox.width;
41341                 height = bbox.height;
41342                 x = bbox.x;
41343                 y = bbox.y;
41344                 if (me.viewBox) {
41345                     me.surface.setViewBox(x, y, width, height);
41346                 }
41347                 else {
41348                     
41349                     me.autoSizeSurface();
41350                 }
41351             }
41352         }
41353     },
41354
41355     //@private
41356
41357     autoSizeSurface: function() {
41358         var me = this,
41359             items = me.surface.items,
41360             bbox = items.getBBox(),
41361             width = bbox.width,
41362             height = bbox.height;
41363         items.setAttributes({
41364             translate: {
41365                 x: -bbox.x,
41366                 
41367                 y: -bbox.y + (+Ext.isOpera)
41368             }
41369         }, true);
41370         if (me.rendered) {
41371             me.setSize(width, height);
41372             me.surface.setSize(width, height);
41373         }
41374         else {
41375             me.surface.setSize(width, height);
41376         }
41377         me.el.setSize(width, height);
41378     },
41379
41380     
41381     createSurface: function() {
41382         var surface = Ext.draw.Surface.create(Ext.apply({}, {
41383                 width: this.width,
41384                 height: this.height,
41385                 renderTo: this.el
41386             }, this.initialConfig));
41387         if (!surface) {
41388             
41389             return false;
41390         }
41391         this.surface = surface;
41392
41393
41394         function refire(eventName) {
41395             return function(e) {
41396                 this.fireEvent(eventName, e);
41397             };
41398         }
41399
41400         surface.on({
41401             scope: this,
41402             mouseup: refire('mouseup'),
41403             mousedown: refire('mousedown'),
41404             mousemove: refire('mousemove'),
41405             mouseenter: refire('mouseenter'),
41406             mouseleave: refire('mouseleave'),
41407             click: refire('click')
41408         });
41409     },
41410
41411
41412     
41413     onDestroy: function() {
41414         var surface = this.surface;
41415         if (surface) {
41416             surface.destroy();
41417         }
41418         this.callParent(arguments);
41419     }
41420
41421 });
41422
41423
41424 Ext.define('Ext.chart.LegendItem', {
41425
41426     
41427
41428     extend: 'Ext.draw.CompositeSprite',
41429
41430     requires: ['Ext.chart.Shape'],
41431
41432     
41433
41434     
41435     x: 0,
41436     y: 0,
41437     zIndex: 500,
41438
41439     constructor: function(config) {
41440         this.callParent(arguments);
41441         this.createLegend(config);
41442     },
41443
41444     
41445     createLegend: function(config) {
41446         var me = this,
41447             index = config.yFieldIndex,
41448             series = me.series,
41449             seriesType = series.type,
41450             idx = me.yFieldIndex,
41451             legend = me.legend,
41452             surface = me.surface,
41453             refX = legend.x + me.x,
41454             refY = legend.y + me.y,
41455             bbox, z = me.zIndex,
41456             markerConfig, label, mask,
41457             radius, toggle = false,
41458             seriesStyle = Ext.apply(series.seriesStyle, series.style);
41459
41460         function getSeriesProp(name) {
41461             var val = series[name];
41462             return (Ext.isArray(val) ? val[idx] : val);
41463         }
41464         
41465         label = me.add('label', surface.add({
41466             type: 'text',
41467             x: 20,
41468             y: 0,
41469             zIndex: z || 0,
41470             font: legend.labelFont,
41471             text: getSeriesProp('title') || getSeriesProp('yField')
41472         }));
41473
41474         
41475         if (seriesType === 'line' || seriesType === 'scatter') {
41476             if(seriesType === 'line') {
41477                 me.add('line', surface.add({
41478                     type: 'path',
41479                     path: 'M0.5,0.5L16.5,0.5',
41480                     zIndex: z,
41481                     "stroke-width": series.lineWidth,
41482                     "stroke-linejoin": "round",
41483                     "stroke-dasharray": series.dash,
41484                     stroke: seriesStyle.stroke || '#000',
41485                     style: {
41486                         cursor: 'pointer'
41487                     }
41488                 }));
41489             }
41490             if (series.showMarkers || seriesType === 'scatter') {
41491                 markerConfig = Ext.apply(series.markerStyle, series.markerConfig || {});
41492                 me.add('marker', Ext.chart.Shape[markerConfig.type](surface, {
41493                     fill: markerConfig.fill,
41494                     x: 8.5,
41495                     y: 0.5,
41496                     zIndex: z,
41497                     radius: markerConfig.radius || markerConfig.size,
41498                     style: {
41499                         cursor: 'pointer'
41500                     }
41501                 }));
41502             }
41503         }
41504         
41505         else {
41506             me.add('box', surface.add({
41507                 type: 'rect',
41508                 zIndex: z,
41509                 x: 0,
41510                 y: 0,
41511                 width: 12,
41512                 height: 12,
41513                 fill: series.getLegendColor(index),
41514                 style: {
41515                     cursor: 'pointer'
41516                 }
41517             }));
41518         }
41519         
41520         me.setAttributes({
41521             hidden: false
41522         }, true);
41523         
41524         bbox = me.getBBox();
41525         
41526         mask = me.add('mask', surface.add({
41527             type: 'rect',
41528             x: bbox.x,
41529             y: bbox.y,
41530             width: bbox.width || 20,
41531             height: bbox.height || 20,
41532             zIndex: (z || 0) + 1000,
41533             fill: '#f00',
41534             opacity: 0,
41535             style: {
41536                 'cursor': 'pointer'
41537             }
41538         }));
41539
41540         
41541         me.on('mouseover', function() {
41542             label.setStyle({
41543                 'font-weight': 'bold'
41544             });
41545             mask.setStyle({
41546                 'cursor': 'pointer'
41547             });
41548             series._index = index;
41549             series.highlightItem();
41550         }, me);
41551
41552         me.on('mouseout', function() {
41553             label.setStyle({
41554                 'font-weight': 'normal'
41555             });
41556             series._index = index;
41557             series.unHighlightItem();
41558         }, me);
41559         
41560         if (!series.visibleInLegend(index)) {
41561             toggle = true;
41562             label.setAttributes({
41563                opacity: 0.5
41564             }, true);
41565         }
41566
41567         me.on('mousedown', function() {
41568             if (!toggle) {
41569                 series.hideAll();
41570                 label.setAttributes({
41571                     opacity: 0.5
41572                 }, true);
41573             } else {
41574                 series.showAll();
41575                 label.setAttributes({
41576                     opacity: 1
41577                 }, true);
41578             }
41579             toggle = !toggle;
41580         }, me);
41581         me.updatePosition({x:0, y:0}); 
41582     },
41583
41584     
41585     updatePosition: function(relativeTo) {
41586         var me = this,
41587             items = me.items,
41588             ln = items.length,
41589             i = 0,
41590             item;
41591         if (!relativeTo) {
41592             relativeTo = me.legend;
41593         }
41594         for (; i < ln; i++) {
41595             item = items[i];
41596             switch (item.type) {
41597                 case 'text':
41598                     item.setAttributes({
41599                         x: 20 + relativeTo.x + me.x,
41600                         y: relativeTo.y + me.y
41601                     }, true);
41602                     break;
41603                 case 'rect':
41604                     item.setAttributes({
41605                         translate: {
41606                             x: relativeTo.x + me.x,
41607                             y: relativeTo.y + me.y - 6
41608                         }
41609                     }, true);
41610                     break;
41611                 default:
41612                     item.setAttributes({
41613                         translate: {
41614                             x: relativeTo.x + me.x,
41615                             y: relativeTo.y + me.y
41616                         }
41617                     }, true);
41618             }
41619         }
41620     }
41621 });
41622
41623
41624 Ext.define('Ext.chart.Legend', {
41625
41626     
41627
41628     requires: ['Ext.chart.LegendItem'],
41629
41630     
41631
41632     
41633     visible: true,
41634
41635     
41636     position: 'bottom',
41637
41638     
41639     x: 0,
41640
41641     
41642     y: 0,
41643
41644     
41645     labelFont: '12px Helvetica, sans-serif',
41646
41647     
41648     boxStroke: '#000',
41649
41650     
41651     boxStrokeWidth: 1,
41652
41653     
41654     boxFill: '#FFF',
41655
41656     
41657     itemSpacing: 10,
41658
41659     
41660     padding: 5,
41661
41662     
41663     width: 0,
41664     
41665     height: 0,
41666
41667     
41668     boxZIndex: 100,
41669
41670     
41671     constructor: function(config) {
41672         var me = this;
41673         if (config) {
41674             Ext.apply(me, config);
41675         }
41676         me.items = [];
41677         
41678         me.isVertical = ("left|right|float".indexOf(me.position) !== -1);
41679
41680         
41681         me.origX = me.x;
41682         me.origY = me.y;
41683     },
41684
41685     
41686     create: function() {
41687         var me = this;
41688         me.createBox();
41689         me.createItems();
41690         if (!me.created && me.isDisplayed()) {
41691             me.created = true;
41692
41693             
41694             me.chart.series.each(function(series) {
41695                 series.on('titlechange', function() {
41696                     me.create();
41697                     me.updatePosition();
41698                 });
41699             });
41700         }
41701     },
41702
41703     
41704     isDisplayed: function() {
41705         return this.visible && this.chart.series.findIndex('showInLegend', true) !== -1;
41706     },
41707
41708     
41709     createItems: function() {
41710         var me = this,
41711             chart = me.chart,
41712             surface = chart.surface,
41713             items = me.items,
41714             padding = me.padding,
41715             itemSpacing = me.itemSpacing,
41716             spacingOffset = 2,
41717             maxWidth = 0,
41718             maxHeight = 0,
41719             totalWidth = 0,
41720             totalHeight = 0,
41721             vertical = me.isVertical,
41722             math = Math,
41723             mfloor = math.floor,
41724             mmax = math.max,
41725             index = 0,
41726             i = 0,
41727             len = items ? items.length : 0,
41728             x, y, spacing, item, bbox, height, width;
41729
41730         
41731         if (len) {
41732             for (; i < len; i++) {
41733                 items[i].destroy();
41734             }
41735         }
41736         
41737         items.length = [];
41738         
41739         
41740         chart.series.each(function(series, i) {
41741             if (series.showInLegend) {
41742                 Ext.each([].concat(series.yField), function(field, j) {
41743                     item = Ext.create('Ext.chart.LegendItem', {
41744                         legend: this,
41745                         series: series,
41746                         surface: chart.surface,
41747                         yFieldIndex: j
41748                     });
41749                     bbox = item.getBBox();
41750
41751                     
41752                     width = bbox.width;
41753                     height = bbox.height;
41754
41755                     if (i + j === 0) {
41756                         spacing = vertical ? padding + height / 2 : padding;
41757                     }
41758                     else {
41759                         spacing = itemSpacing / (vertical ? 2 : 1);
41760                     }
41761                     
41762                     item.x = mfloor(vertical ? padding : totalWidth + spacing);
41763                     item.y = mfloor(vertical ? totalHeight + spacing : padding + height / 2);
41764
41765                     
41766                     totalWidth += width + spacing;
41767                     totalHeight += height + spacing;
41768                     maxWidth = mmax(maxWidth, width);
41769                     maxHeight = mmax(maxHeight, height);
41770
41771                     items.push(item);
41772                 }, this);
41773             }
41774         }, me);
41775
41776         
41777         me.width = mfloor((vertical ? maxWidth : totalWidth) + padding * 2);
41778         if (vertical && items.length === 1) {
41779             spacingOffset = 1;
41780         }
41781         me.height = mfloor((vertical ? totalHeight - spacingOffset * spacing : maxHeight) + (padding * 2));
41782         me.itemHeight = maxHeight;
41783     },
41784
41785     
41786     getBBox: function() {
41787         var me = this;
41788         return {
41789             x: Math.round(me.x) - me.boxStrokeWidth / 2,
41790             y: Math.round(me.y) - me.boxStrokeWidth / 2,
41791             width: me.width,
41792             height: me.height
41793         };
41794     },
41795
41796     
41797     createBox: function() {
41798         var me = this,
41799             box;
41800
41801         if (me.boxSprite) {
41802             me.boxSprite.destroy();
41803         }
41804         
41805         box = me.boxSprite = me.chart.surface.add(Ext.apply({
41806             type: 'rect',
41807             stroke: me.boxStroke,
41808             "stroke-width": me.boxStrokeWidth,
41809             fill: me.boxFill,
41810             zIndex: me.boxZIndex
41811         }, me.getBBox()));
41812
41813         box.redraw();
41814     },
41815
41816     
41817     updatePosition: function() {
41818         var me = this,
41819             x, y,
41820             legendWidth = me.width,
41821             legendHeight = me.height,
41822             padding = me.padding,
41823             chart = me.chart,
41824             chartBBox = chart.chartBBox,
41825             insets = chart.insetPadding,
41826             chartWidth = chartBBox.width - (insets * 2),
41827             chartHeight = chartBBox.height - (insets * 2),
41828             chartX = chartBBox.x + insets,
41829             chartY = chartBBox.y + insets,
41830             surface = chart.surface,
41831             mfloor = Math.floor;
41832
41833         if (me.isDisplayed()) {
41834             
41835             switch(me.position) {
41836                 case "left":
41837                     x = insets;
41838                     y = mfloor(chartY + chartHeight / 2 - legendHeight / 2);
41839                     break;
41840                 case "right":
41841                     x = mfloor(surface.width - legendWidth) - insets;
41842                     y = mfloor(chartY + chartHeight / 2 - legendHeight / 2);
41843                     break;
41844                 case "top":
41845                     x = mfloor(chartX + chartWidth / 2 - legendWidth / 2);
41846                     y = insets;
41847                     break;
41848                 case "bottom":
41849                     x = mfloor(chartX + chartWidth / 2 - legendWidth / 2);
41850                     y = mfloor(surface.height - legendHeight) - insets;
41851                     break;
41852                 default:
41853                     x = mfloor(me.origX) + insets;
41854                     y = mfloor(me.origY) + insets;
41855             }
41856             me.x = x;
41857             me.y = y;
41858
41859             
41860             Ext.each(me.items, function(item) {
41861                 item.updatePosition();
41862             });
41863             
41864             me.boxSprite.setAttributes(me.getBBox(), true);
41865         }
41866     }
41867 });
41868
41869
41870 Ext.define('Ext.chart.Chart', {
41871
41872     
41873
41874     alias: 'widget.chart',
41875
41876     extend: 'Ext.draw.Component',
41877     
41878     mixins: {
41879         themeManager: 'Ext.chart.theme.Theme',
41880         mask: 'Ext.chart.Mask',
41881         navigation: 'Ext.chart.Navigation'
41882     },
41883
41884     requires: [
41885         'Ext.util.MixedCollection',
41886         'Ext.data.StoreManager',
41887         'Ext.chart.Legend',
41888         'Ext.util.DelayedTask'
41889     ],
41890
41891     
41892
41893     
41894     viewBox: false,
41895
41896     
41897
41898     
41899     animate: false,
41900
41901     
41902     legend: false,
41903
41904     
41905     insetPadding: 10,
41906
41907     
41908     enginePriority: ['Svg', 'Vml'],
41909
41910     
41911     background: false,
41912
41913     
41914
41915     
41916
41917     
41918
41919     
41920
41921     constructor: function(config) {
41922         var me = this,
41923             defaultAnim;
41924             
41925         config = Ext.apply({}, config);
41926         me.initTheme(config.theme || me.theme);
41927         if (me.gradients) {
41928             Ext.apply(config, { gradients: me.gradients });
41929         }
41930         if (me.background) {
41931             Ext.apply(config, { background: me.background });
41932         }
41933         if (config.animate) {
41934             defaultAnim = {
41935                 easing: 'ease',
41936                 duration: 500
41937             };
41938             if (Ext.isObject(config.animate)) {
41939                 config.animate = Ext.applyIf(config.animate, defaultAnim);
41940             }
41941             else {
41942                 config.animate = defaultAnim;
41943             }
41944         }
41945         me.mixins.mask.constructor.call(me, config);
41946         me.mixins.navigation.constructor.call(me, config);
41947         me.callParent([config]);
41948     },
41949     
41950     getChartStore: function(){
41951         return this.substore || this.store;    
41952     },
41953
41954     initComponent: function() {
41955         var me = this,
41956             axes,
41957             series;
41958         me.callParent();
41959         me.addEvents(
41960             'itemmousedown',
41961             'itemmouseup',
41962             'itemmouseover',
41963             'itemmouseout',
41964             'itemclick',
41965             'itemdoubleclick',
41966             'itemdragstart',
41967             'itemdrag',
41968             'itemdragend',
41969             
41970             'beforerefresh',
41971             
41972             'refresh'
41973         );
41974         Ext.applyIf(me, {
41975             zoom: {
41976                 width: 1,
41977                 height: 1,
41978                 x: 0,
41979                 y: 0
41980             }
41981         });
41982         me.maxGutter = [0, 0];
41983         me.store = Ext.data.StoreManager.lookup(me.store);
41984         axes = me.axes;
41985         me.axes = Ext.create('Ext.util.MixedCollection', false, function(a) { return a.position; });
41986         if (axes) {
41987             me.axes.addAll(axes);
41988         }
41989         series = me.series;
41990         me.series = Ext.create('Ext.util.MixedCollection', false, function(a) { return a.seriesId || (a.seriesId = Ext.id(null, 'ext-chart-series-')); });
41991         if (series) {
41992             me.series.addAll(series);
41993         }
41994         if (me.legend !== false) {
41995             me.legend = Ext.create('Ext.chart.Legend', Ext.applyIf({chart:me}, me.legend));
41996         }
41997
41998         me.on({
41999             mousemove: me.onMouseMove,
42000             mouseleave: me.onMouseLeave,
42001             mousedown: me.onMouseDown,
42002             mouseup: me.onMouseUp,
42003             scope: me
42004         });
42005     },
42006
42007     
42008     afterComponentLayout: function(width, height) {
42009         var me = this;
42010         if (Ext.isNumber(width) && Ext.isNumber(height)) {
42011             me.curWidth = width;
42012             me.curHeight = height;
42013             me.redraw(true);
42014         }
42015         this.callParent(arguments);
42016     },
42017
42018     
42019     redraw: function(resize) {
42020         var me = this,
42021             chartBBox = me.chartBBox = {
42022                 x: 0,
42023                 y: 0,
42024                 height: me.curHeight,
42025                 width: me.curWidth
42026             },
42027             legend = me.legend;
42028         me.surface.setSize(chartBBox.width, chartBBox.height);
42029         
42030         me.series.each(me.initializeSeries, me);
42031         me.axes.each(me.initializeAxis, me);
42032         
42033         
42034         me.axes.each(function(axis) {
42035             axis.processView();
42036         });
42037         me.axes.each(function(axis) {
42038             axis.drawAxis(true);
42039         });
42040
42041         
42042         if (legend !== false) {
42043             legend.create();
42044         }
42045
42046         
42047         me.alignAxes();
42048
42049         
42050         if (me.legend !== false) {
42051             legend.updatePosition();
42052         }
42053
42054         
42055         me.getMaxGutter();
42056
42057         
42058         me.resizing = !!resize;
42059
42060         me.axes.each(me.drawAxis, me);
42061         me.series.each(me.drawCharts, me);
42062         me.resizing = false;
42063     },
42064
42065     
42066     afterRender: function() {
42067         var ref,
42068             me = this;
42069         this.callParent();
42070
42071         if (me.categoryNames) {
42072             me.setCategoryNames(me.categoryNames);
42073         }
42074
42075         if (me.tipRenderer) {
42076             ref = me.getFunctionRef(me.tipRenderer);
42077             me.setTipRenderer(ref.fn, ref.scope);
42078         }
42079         me.bindStore(me.store, true);
42080         me.refresh();
42081     },
42082
42083     
42084     getEventXY: function(e) {
42085         var me = this,
42086             box = this.surface.getRegion(),
42087             pageXY = e.getXY(),
42088             x = pageXY[0] - box.left,
42089             y = pageXY[1] - box.top;
42090         return [x, y];
42091     },
42092
42093     
42094     onClick: function(e) {
42095         var me = this,
42096             position = me.getEventXY(e),
42097             item;
42098
42099         
42100         
42101         me.series.each(function(series) {
42102             if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
42103                 if (series.getItemForPoint) {
42104                     item = series.getItemForPoint(position[0], position[1]);
42105                     if (item) {
42106                         series.fireEvent('itemclick', item);
42107                     }
42108                 }
42109             }
42110         }, me);
42111     },
42112
42113     
42114     onMouseDown: function(e) {
42115         var me = this,
42116             position = me.getEventXY(e),
42117             item;
42118
42119         if (me.mask) {
42120             me.mixins.mask.onMouseDown.call(me, e);
42121         }
42122         
42123         
42124         me.series.each(function(series) {
42125             if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
42126                 if (series.getItemForPoint) {
42127                     item = series.getItemForPoint(position[0], position[1]);
42128                     if (item) {
42129                         series.fireEvent('itemmousedown', item);
42130                     }
42131                 }
42132             }
42133         }, me);
42134     },
42135
42136     
42137     onMouseUp: function(e) {
42138         var me = this,
42139             position = me.getEventXY(e),
42140             item;
42141
42142         if (me.mask) {
42143             me.mixins.mask.onMouseUp.call(me, e);
42144         }
42145         
42146         
42147         me.series.each(function(series) {
42148             if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
42149                 if (series.getItemForPoint) {
42150                     item = series.getItemForPoint(position[0], position[1]);
42151                     if (item) {
42152                         series.fireEvent('itemmouseup', item);
42153                     }
42154                 }
42155             }
42156         }, me);
42157     },
42158
42159     
42160     onMouseMove: function(e) {
42161         var me = this,
42162             position = me.getEventXY(e),
42163             item, last, storeItem, storeField;
42164
42165         if (me.mask) {
42166             me.mixins.mask.onMouseMove.call(me, e);
42167         }
42168         
42169         
42170         me.series.each(function(series) {
42171             if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
42172                 if (series.getItemForPoint) {
42173                     item = series.getItemForPoint(position[0], position[1]);
42174                     last = series._lastItemForPoint;
42175                     storeItem = series._lastStoreItem;
42176                     storeField = series._lastStoreField;
42177
42178
42179                     if (item !== last || item && (item.storeItem != storeItem || item.storeField != storeField)) {
42180                         if (last) {
42181                             series.fireEvent('itemmouseout', last);
42182                             delete series._lastItemForPoint;
42183                             delete series._lastStoreField;
42184                             delete series._lastStoreItem;
42185                         }
42186                         if (item) {
42187                             series.fireEvent('itemmouseover', item);
42188                             series._lastItemForPoint = item;
42189                             series._lastStoreItem = item.storeItem;
42190                             series._lastStoreField = item.storeField;
42191                         }
42192                     }
42193                 }
42194             } else {
42195                 last = series._lastItemForPoint;
42196                 if (last) {
42197                     series.fireEvent('itemmouseout', last);
42198                     delete series._lastItemForPoint;
42199                     delete series._lastStoreField;
42200                     delete series._lastStoreItem;
42201                 }
42202             }
42203         }, me);
42204     },
42205
42206     
42207     onMouseLeave: function(e) {
42208         var me = this;
42209         if (me.mask) {
42210             me.mixins.mask.onMouseLeave.call(me, e);
42211         }
42212         me.series.each(function(series) {
42213             delete series._lastItemForPoint;
42214         });
42215     },
42216
42217     
42218     delayRefresh: function() {
42219         var me = this;
42220         if (!me.refreshTask) {
42221             me.refreshTask = Ext.create('Ext.util.DelayedTask', me.refresh, me);
42222         }
42223         me.refreshTask.delay(me.refreshBuffer);
42224     },
42225
42226     
42227     refresh: function() {
42228         var me = this;
42229         if (me.rendered && me.curWidth !== undefined && me.curHeight !== undefined) {
42230             if (me.fireEvent('beforerefresh', me) !== false) {
42231                 me.redraw();
42232                 me.fireEvent('refresh', me);
42233             }
42234         }
42235     },
42236
42237     
42238     bindStore: function(store, initial) {
42239         var me = this;
42240         if (!initial && me.store) {
42241             if (store !== me.store && me.store.autoDestroy) {
42242                 me.store.destroyStore();
42243             }
42244             else {
42245                 me.store.un('datachanged', me.refresh, me);
42246                 me.store.un('add', me.delayRefresh, me);
42247                 me.store.un('remove', me.delayRefresh, me);
42248                 me.store.un('update', me.delayRefresh, me);
42249                 me.store.un('clear', me.refresh, me);
42250             }
42251         }
42252         if (store) {
42253             store = Ext.data.StoreManager.lookup(store);
42254             store.on({
42255                 scope: me,
42256                 datachanged: me.refresh,
42257                 add: me.delayRefresh,
42258                 remove: me.delayRefresh,
42259                 update: me.delayRefresh,
42260                 clear: me.refresh
42261             });
42262         }
42263         me.store = store;
42264         if (store && !initial) {
42265             me.refresh();
42266         }
42267     },
42268
42269     
42270     initializeAxis: function(axis) {
42271         var me = this,
42272             chartBBox = me.chartBBox,
42273             w = chartBBox.width,
42274             h = chartBBox.height,
42275             x = chartBBox.x,
42276             y = chartBBox.y,
42277             themeAttrs = me.themeAttrs,
42278             config = {
42279                 chart: me
42280             };
42281         if (themeAttrs) {
42282             config.axisStyle = Ext.apply({}, themeAttrs.axis);
42283             config.axisLabelLeftStyle = Ext.apply({}, themeAttrs.axisLabelLeft);
42284             config.axisLabelRightStyle = Ext.apply({}, themeAttrs.axisLabelRight);
42285             config.axisLabelTopStyle = Ext.apply({}, themeAttrs.axisLabelTop);
42286             config.axisLabelBottomStyle = Ext.apply({}, themeAttrs.axisLabelBottom);
42287             config.axisTitleLeftStyle = Ext.apply({}, themeAttrs.axisTitleLeft);
42288             config.axisTitleRightStyle = Ext.apply({}, themeAttrs.axisTitleRight);
42289             config.axisTitleTopStyle = Ext.apply({}, themeAttrs.axisTitleTop);
42290             config.axisTitleBottomStyle = Ext.apply({}, themeAttrs.axisTitleBottom);
42291         }
42292         switch (axis.position) {
42293             case 'top':
42294                 Ext.apply(config, {
42295                     length: w,
42296                     width: h,
42297                     x: x,
42298                     y: y
42299                 });
42300             break;
42301             case 'bottom':
42302                 Ext.apply(config, {
42303                     length: w,
42304                     width: h,
42305                     x: x,
42306                     y: h
42307                 });
42308             break;
42309             case 'left':
42310                 Ext.apply(config, {
42311                     length: h,
42312                     width: w,
42313                     x: x,
42314                     y: h
42315                 });
42316             break;
42317             case 'right':
42318                 Ext.apply(config, {
42319                     length: h,
42320                     width: w,
42321                     x: w,
42322                     y: h
42323                 });
42324             break;
42325         }
42326         if (!axis.chart) {
42327             Ext.apply(config, axis);
42328             axis = me.axes.replace(Ext.createByAlias('axis.' + axis.type.toLowerCase(), config));
42329         }
42330         else {
42331             Ext.apply(axis, config);
42332         }
42333     },
42334
42335
42336     
42337     alignAxes: function() {
42338         var me = this,
42339             axes = me.axes,
42340             legend = me.legend,
42341             edges = ['top', 'right', 'bottom', 'left'],
42342             chartBBox,
42343             insetPadding = me.insetPadding,
42344             insets = {
42345                 top: insetPadding,
42346                 right: insetPadding,
42347                 bottom: insetPadding,
42348                 left: insetPadding
42349             };
42350
42351         function getAxis(edge) {
42352             var i = axes.findIndex('position', edge);
42353             return (i < 0) ? null : axes.getAt(i);
42354         }
42355
42356         
42357         Ext.each(edges, function(edge) {
42358             var isVertical = (edge === 'left' || edge === 'right'),
42359                 axis = getAxis(edge),
42360                 bbox;
42361
42362             
42363             if (legend !== false) {
42364                 if (legend.position === edge) {
42365                     bbox = legend.getBBox();
42366                     insets[edge] += (isVertical ? bbox.width : bbox.height) + insets[edge];
42367                 }
42368             }
42369
42370             
42371             
42372             if (axis && axis.bbox) {
42373                 bbox = axis.bbox;
42374                 insets[edge] += (isVertical ? bbox.width : bbox.height);
42375             }
42376         });
42377         
42378         chartBBox = {
42379             x: insets.left,
42380             y: insets.top,
42381             width: me.curWidth - insets.left - insets.right,
42382             height: me.curHeight - insets.top - insets.bottom
42383         };
42384         me.chartBBox = chartBBox;
42385
42386         
42387         
42388         axes.each(function(axis) {
42389             var pos = axis.position,
42390                 isVertical = (pos === 'left' || pos === 'right');
42391
42392             axis.x = (pos === 'right' ? chartBBox.x + chartBBox.width : chartBBox.x);
42393             axis.y = (pos === 'top' ? chartBBox.y : chartBBox.y + chartBBox.height);
42394             axis.width = (isVertical ? chartBBox.width : chartBBox.height);
42395             axis.length = (isVertical ? chartBBox.height : chartBBox.width);
42396         });
42397     },
42398
42399     
42400     initializeSeries: function(series, idx) {
42401         var me = this,
42402             themeAttrs = me.themeAttrs,
42403             seriesObj, markerObj, seriesThemes, st,
42404             markerThemes, colorArrayStyle = [],
42405             i = 0, l,
42406             config = {
42407                 chart: me,
42408                 seriesId: series.seriesId
42409             };
42410         if (themeAttrs) {
42411             seriesThemes = themeAttrs.seriesThemes;
42412             markerThemes = themeAttrs.markerThemes;
42413             seriesObj = Ext.apply({}, themeAttrs.series);
42414             markerObj = Ext.apply({}, themeAttrs.marker);
42415             config.seriesStyle = Ext.apply(seriesObj, seriesThemes[idx % seriesThemes.length]);
42416             config.seriesLabelStyle = Ext.apply({}, themeAttrs.seriesLabel);
42417             config.markerStyle = Ext.apply(markerObj, markerThemes[idx % markerThemes.length]);
42418             if (themeAttrs.colors) {
42419                 config.colorArrayStyle = themeAttrs.colors;
42420             } else {
42421                 colorArrayStyle = [];
42422                 for (l = seriesThemes.length; i < l; i++) {
42423                     st = seriesThemes[i];
42424                     if (st.fill || st.stroke) {
42425                         colorArrayStyle.push(st.fill || st.stroke);
42426                     }
42427                 }
42428                 if (colorArrayStyle.length) {
42429                     config.colorArrayStyle = colorArrayStyle;
42430                 }
42431             }
42432             config.seriesIdx = idx;
42433         }
42434         if (series instanceof Ext.chart.series.Series) {
42435             Ext.apply(series, config);
42436         } else {
42437             Ext.applyIf(config, series);
42438             series = me.series.replace(Ext.createByAlias('series.' + series.type.toLowerCase(), config));
42439         }
42440         if (series.initialize) {
42441             series.initialize();
42442         }
42443     },
42444
42445     
42446     getMaxGutter: function() {
42447         var me = this,
42448             maxGutter = [0, 0];
42449         me.series.each(function(s) {
42450             var gutter = s.getGutters && s.getGutters() || [0, 0];
42451             maxGutter[0] = Math.max(maxGutter[0], gutter[0]);
42452             maxGutter[1] = Math.max(maxGutter[1], gutter[1]);
42453         });
42454         me.maxGutter = maxGutter;
42455     },
42456
42457     
42458     drawAxis: function(axis) {
42459         axis.drawAxis();
42460     },
42461
42462     
42463     drawCharts: function(series) {
42464         series.triggerafterrender = false;
42465         series.drawSeries();
42466         if (!this.animate) {
42467             series.fireEvent('afterrender');
42468         }
42469     },
42470
42471     
42472     destroy: function() {
42473         Ext.destroy(this.surface);
42474         this.bindStore(null);
42475         this.callParent(arguments);
42476     }
42477 });
42478
42479
42480 Ext.define('Ext.chart.Highlight', {
42481
42482     
42483
42484     requires: ['Ext.fx.Anim'],
42485
42486     
42487
42488     
42489     highlight: false,
42490
42491     highlightCfg : null,
42492
42493     constructor: function(config) {
42494         if (config.highlight) {
42495             if (config.highlight !== true) { 
42496                 this.highlightCfg = Ext.apply({}, config.highlight);
42497             }
42498             else {
42499                 this.highlightCfg = {
42500                     fill: '#fdd',
42501                     radius: 20,
42502                     lineWidth: 5,
42503                     stroke: '#f55'
42504                 };
42505             }
42506         }
42507     },
42508
42509     
42510     highlightItem: function(item) {
42511         if (!item) {
42512             return;
42513         }
42514         
42515         var me = this,
42516             sprite = item.sprite,
42517             opts = me.highlightCfg,
42518             surface = me.chart.surface,
42519             animate = me.chart.animate,
42520             p, from, to, pi;
42521
42522         if (!me.highlight || !sprite || sprite._highlighted) {
42523             return;
42524         }
42525         if (sprite._anim) {
42526             sprite._anim.paused = true;
42527         }
42528         sprite._highlighted = true;
42529         if (!sprite._defaults) {
42530             sprite._defaults = Ext.apply({}, sprite.attr);
42531             from = {};
42532             to = {};
42533             for (p in opts) {
42534                 if (! (p in sprite._defaults)) {
42535                     sprite._defaults[p] = surface.availableAttrs[p];
42536                 }
42537                 from[p] = sprite._defaults[p];
42538                 to[p] = opts[p];
42539                 if (Ext.isObject(opts[p])) {
42540                     from[p] = {};
42541                     to[p] = {};
42542                     Ext.apply(sprite._defaults[p], sprite.attr[p]);
42543                     Ext.apply(from[p], sprite._defaults[p]);
42544                     for (pi in sprite._defaults[p]) {
42545                         if (! (pi in opts[p])) {
42546                             to[p][pi] = from[p][pi];
42547                         } else {
42548                             to[p][pi] = opts[p][pi];
42549                         }
42550                     }
42551                     for (pi in opts[p]) {
42552                         if (! (pi in to[p])) {
42553                             to[p][pi] = opts[p][pi];
42554                         }
42555                     }
42556                 }
42557             }
42558             sprite._from = from;
42559             sprite._to = to;
42560             sprite._endStyle = to;
42561         }
42562         if (animate) {
42563             sprite._anim = Ext.create('Ext.fx.Anim', {
42564                 target: sprite,
42565                 from: sprite._from,
42566                 to: sprite._to,
42567                 duration: 150
42568             });
42569         } else {
42570             sprite.setAttributes(sprite._to, true);
42571         }
42572     },
42573
42574     
42575     unHighlightItem: function() {
42576         if (!this.highlight || !this.items) {
42577             return;
42578         }
42579
42580         var me = this,
42581             items = me.items,
42582             len = items.length,
42583             opts = me.highlightCfg,
42584             animate = me.chart.animate,
42585             i = 0,
42586             obj, p, sprite;
42587
42588         for (; i < len; i++) {
42589             if (!items[i]) {
42590                 continue;
42591             }
42592             sprite = items[i].sprite;
42593             if (sprite && sprite._highlighted) {
42594                 if (sprite._anim) {
42595                     sprite._anim.paused = true;
42596                 }
42597                 obj = {};
42598                 for (p in opts) {
42599                     if (Ext.isObject(sprite._defaults[p])) {
42600                         obj[p] = {};
42601                         Ext.apply(obj[p], sprite._defaults[p]);
42602                     }
42603                     else {
42604                         obj[p] = sprite._defaults[p];
42605                     }
42606                 }
42607                 if (animate) {
42608                     
42609                     sprite._endStyle = obj;
42610                     sprite._anim = Ext.create('Ext.fx.Anim', {
42611                         target: sprite,
42612                         to: obj,
42613                         duration: 150
42614                     });
42615                 }
42616                 else {
42617                     sprite.setAttributes(obj, true);
42618                 }
42619                 delete sprite._highlighted;
42620                 
42621             }
42622         }
42623     },
42624
42625     cleanHighlights: function() {
42626         if (!this.highlight) {
42627             return;
42628         }
42629
42630         var group = this.group,
42631             markerGroup = this.markerGroup,
42632             i = 0,
42633             l;
42634         for (l = group.getCount(); i < l; i++) {
42635             delete group.getAt(i)._defaults;
42636         }
42637         if (markerGroup) {
42638             for (l = markerGroup.getCount(); i < l; i++) {
42639                 delete markerGroup.getAt(i)._defaults;
42640             }
42641         }
42642     }
42643 });
42644
42645 Ext.define('Ext.chart.Label', {
42646
42647     
42648
42649     requires: ['Ext.draw.Color'],
42650
42651     
42652
42653     
42654
42655     //@private a regex to parse url type colors.
42656
42657     colorStringRe: /url\s*\(\s*#([^\/)]+)\s*\)/,
42658
42659     //@private the mixin constructor. Used internally by Series.
42660
42661     constructor: function(config) {
42662         var me = this;
42663         me.label = Ext.applyIf(me.label || {},
42664         {
42665             display: "none",
42666             color: "#000",
42667             field: "name",
42668             minMargin: 50,
42669             font: "11px Helvetica, sans-serif",
42670             orientation: "horizontal",
42671             renderer: function(v) {
42672                 return v;
42673             }
42674         });
42675
42676         if (me.label.display !== 'none') {
42677             me.labelsGroup = me.chart.surface.getGroup(me.seriesId + '-labels');
42678         }
42679     },
42680
42681     //@private a method to render all labels in the labelGroup
42682
42683     renderLabels: function() {
42684         var me = this,
42685             chart = me.chart,
42686             gradients = chart.gradients,
42687             items = me.items,
42688             animate = chart.animate,
42689             config = me.label,
42690             display = config.display,
42691             color = config.color,
42692             field = [].concat(config.field),
42693             group = me.labelsGroup,
42694             groupLength = (group || 0) && group.length,
42695             store = me.chart.store,
42696             len = store.getCount(),
42697             itemLength = (items || 0) && items.length,
42698             ratio = itemLength / len,
42699             gradientsCount = (gradients || 0) && gradients.length,
42700             Color = Ext.draw.Color,
42701             hides = [],
42702             gradient, i, count, groupIndex, index, j, k, colorStopTotal, colorStopIndex, colorStop, item, label,
42703             storeItem, sprite, spriteColor, spriteBrightness, labelColor, colorString;
42704
42705         if (display == 'none') {
42706             return;
42707         }
42708         
42709         if(itemLength == 0){
42710             while(groupLength--)
42711                 hides.push(groupLength);
42712         }else{
42713             for (i = 0, count = 0, groupIndex = 0; i < len; i++) {
42714                 index = 0;
42715                 for (j = 0; j < ratio; j++) {
42716                     item = items[count];
42717                     label = group.getAt(groupIndex);
42718                     storeItem = store.getAt(i);
42719                     
42720                     while(this.__excludes && this.__excludes[index] && ratio > 1) {
42721                         if(field[j]){
42722                             hides.push(groupIndex);
42723                         }
42724                         index++;
42725
42726                     }
42727
42728                     if (!item && label) {
42729                         label.hide(true);
42730                         groupIndex++;
42731                     }
42732
42733                     if (item && field[j]) {
42734                         if (!label) {
42735                             label = me.onCreateLabel(storeItem, item, i, display, j, index);
42736                         }
42737                         me.onPlaceLabel(label, storeItem, item, i, display, animate, j, index);
42738                         groupIndex++;
42739
42740                         
42741                         if (config.contrast && item.sprite) {
42742                             sprite = item.sprite;
42743                             
42744                             if (sprite._endStyle) {
42745                                 colorString = sprite._endStyle.fill;
42746                             }
42747                             else if (sprite._to) {
42748                                 colorString = sprite._to.fill;
42749                             }
42750                             else {
42751                                 colorString = sprite.attr.fill;
42752                             }
42753                             colorString = colorString || sprite.attr.fill;
42754
42755                             spriteColor = Color.fromString(colorString);
42756                             
42757                             if (colorString && !spriteColor) {
42758                                 colorString = colorString.match(me.colorStringRe)[1];
42759                                 for (k = 0; k < gradientsCount; k++) {
42760                                     gradient = gradients[k];
42761                                     if (gradient.id == colorString) {
42762                                         
42763                                         colorStop = 0; colorStopTotal = 0;
42764                                         for (colorStopIndex in gradient.stops) {
42765                                             colorStop++;
42766                                             colorStopTotal += Color.fromString(gradient.stops[colorStopIndex].color).getGrayscale();
42767                                         }
42768                                         spriteBrightness = (colorStopTotal / colorStop) / 255;
42769                                         break;
42770                                     }
42771                                 }
42772                             }
42773                             else {
42774                                 spriteBrightness = spriteColor.getGrayscale() / 255;
42775                             }
42776                             if (label.isOutside) {
42777                                 spriteBrightness = 1;
42778                             }
42779                             labelColor = Color.fromString(label.attr.color || label.attr.fill).getHSL();
42780                             labelColor[2] = spriteBrightness > 0.5 ? 0.2 : 0.8;
42781                             label.setAttributes({
42782                                 fill: String(Color.fromHSL.apply({}, labelColor))
42783                             }, true);
42784                         }
42785
42786                     }
42787                     count++;
42788                     index++;
42789                 }
42790             }
42791         }
42792         me.hideLabels(hides);
42793     },
42794     hideLabels: function(hides){
42795         var labelsGroup = this.labelsGroup,
42796             hlen = hides.length;
42797         while(hlen--)
42798             labelsGroup.getAt(hides[hlen]).hide(true);
42799     }
42800 });
42801 Ext.define('Ext.chart.MaskLayer', {
42802     extend: 'Ext.Component',
42803     
42804     constructor: function(config) {
42805         config = Ext.apply(config || {}, {
42806             style: 'position:absolute;background-color:#888;cursor:move;opacity:0.6;border:1px solid #222;'
42807         });
42808         this.callParent([config]);    
42809     },
42810     
42811     initComponent: function() {
42812         var me = this;
42813         me.callParent(arguments);
42814         me.addEvents(
42815             'mousedown',
42816             'mouseup',
42817             'mousemove',
42818             'mouseenter',
42819             'mouseleave'
42820         );
42821     },
42822
42823     initDraggable: function() {
42824         this.callParent(arguments);
42825         this.dd.onStart = function (e) {
42826             var me = this,
42827                 comp = me.comp;
42828     
42829             
42830             this.startPosition = comp.getPosition(true);
42831     
42832             
42833             
42834             if (comp.ghost && !comp.liveDrag) {
42835                  me.proxy = comp.ghost();
42836                  me.dragTarget = me.proxy.header.el;
42837             }
42838     
42839             
42840             if (me.constrain || me.constrainDelegate) {
42841                 me.constrainTo = me.calculateConstrainRegion();
42842             }
42843         };
42844     }
42845 });
42846
42847 Ext.define('Ext.chart.TipSurface', {
42848
42849     
42850
42851     extend: 'Ext.draw.Component',
42852
42853     
42854
42855     spriteArray: false,
42856     renderFirst: true,
42857
42858     constructor: function(config) {
42859         this.callParent([config]);
42860         if (config.sprites) {
42861             this.spriteArray = [].concat(config.sprites);
42862             delete config.sprites;
42863         }
42864     },
42865
42866     onRender: function() {
42867         var me = this,
42868             i = 0,
42869             l = 0,
42870             sp,
42871             sprites;
42872             this.callParent(arguments);
42873         sprites = me.spriteArray;
42874         if (me.renderFirst && sprites) {
42875             me.renderFirst = false;
42876             for (l = sprites.length; i < l; i++) {
42877                 sp = me.surface.add(sprites[i]);
42878                 sp.setAttributes({
42879                     hidden: false
42880                 },
42881                 true);
42882             }
42883         }
42884     }
42885 });
42886
42887
42888 Ext.define('Ext.chart.Tip', {
42889
42890     
42891
42892     requires: ['Ext.tip.ToolTip', 'Ext.chart.TipSurface'],
42893
42894     
42895
42896     constructor: function(config) {
42897         var me = this,
42898             surface,
42899             sprites,
42900             tipSurface;
42901         if (config.tips) {
42902             me.tipTimeout = null;
42903             me.tipConfig = Ext.apply({}, config.tips, {
42904                 renderer: Ext.emptyFn,
42905                 constrainPosition: false
42906             });
42907             me.tooltip = Ext.create('Ext.tip.ToolTip', me.tipConfig);
42908             me.chart.surface.on('mousemove', me.tooltip.onMouseMove, me.tooltip);
42909             me.chart.surface.on('mouseleave', function() {
42910                 me.hideTip();
42911             });
42912             if (me.tipConfig.surface) {
42913                 
42914                 surface = me.tipConfig.surface;
42915                 sprites = surface.sprites;
42916                 tipSurface = Ext.create('Ext.chart.TipSurface', {
42917                     id: 'tipSurfaceComponent',
42918                     sprites: sprites
42919                 });
42920                 if (surface.width && surface.height) {
42921                     tipSurface.setSize(surface.width, surface.height);
42922                 }
42923                 me.tooltip.add(tipSurface);
42924                 me.spriteTip = tipSurface;
42925             }
42926         }
42927     },
42928
42929     showTip: function(item) {
42930         var me = this;
42931         if (!me.tooltip) {
42932             return;
42933         }
42934         clearTimeout(me.tipTimeout);
42935         var tooltip = me.tooltip,
42936             spriteTip = me.spriteTip,
42937             tipConfig = me.tipConfig,
42938             trackMouse = tooltip.trackMouse,
42939             sprite, surface, surfaceExt, pos, x, y;
42940         if (!trackMouse) {
42941             tooltip.trackMouse = true;
42942             sprite = item.sprite;
42943             surface = sprite.surface;
42944             surfaceExt = Ext.get(surface.getId());
42945             if (surfaceExt) {
42946                 pos = surfaceExt.getXY();
42947                 x = pos[0] + (sprite.attr.x || 0) + (sprite.attr.translation && sprite.attr.translation.x || 0);
42948                 y = pos[1] + (sprite.attr.y || 0) + (sprite.attr.translation && sprite.attr.translation.y || 0);
42949                 tooltip.targetXY = [x, y];
42950             }
42951         }
42952         if (spriteTip) {
42953             tipConfig.renderer.call(tooltip, item.storeItem, item, spriteTip.surface);
42954         } else {
42955             tipConfig.renderer.call(tooltip, item.storeItem, item);
42956         }
42957         tooltip.show();
42958         tooltip.trackMouse = trackMouse;
42959     },
42960
42961     hideTip: function(item) {
42962         var tooltip = this.tooltip;
42963         if (!tooltip) {
42964             return;
42965         }
42966         clearTimeout(this.tipTimeout);
42967         this.tipTimeout = setTimeout(function() {
42968             tooltip.hide();
42969         }, 0);
42970     }
42971 });
42972
42973 Ext.define('Ext.chart.axis.Abstract', {
42974
42975     
42976
42977     requires: ['Ext.chart.Chart'],
42978
42979     
42980
42981     
42982     constructor: function(config) {
42983         config = config || {};
42984
42985         var me = this,
42986             pos = config.position || 'left';
42987
42988         pos = pos.charAt(0).toUpperCase() + pos.substring(1);
42989         
42990         config.label = Ext.apply(config['axisLabel' + pos + 'Style'] || {}, config.label || {});
42991         config.axisTitleStyle = Ext.apply(config['axisTitle' + pos + 'Style'] || {}, config.labelTitle || {});
42992         Ext.apply(me, config);
42993         me.fields = [].concat(me.fields);
42994         this.callParent();
42995         me.labels = [];
42996         me.getId();
42997         me.labelGroup = me.chart.surface.getGroup(me.axisId + "-labels");
42998     },
42999
43000     alignment: null,
43001     grid: false,
43002     steps: 10,
43003     x: 0,
43004     y: 0,
43005     minValue: 0,
43006     maxValue: 0,
43007
43008     getId: function() {
43009         return this.axisId || (this.axisId = Ext.id(null, 'ext-axis-'));
43010     },
43011
43012     
43013     processView: Ext.emptyFn,
43014
43015     drawAxis: Ext.emptyFn,
43016     addDisplayAndLabels: Ext.emptyFn
43017 });
43018
43019
43020 Ext.define('Ext.chart.axis.Axis', {
43021
43022     
43023
43024     extend: 'Ext.chart.axis.Abstract',
43025
43026     alternateClassName: 'Ext.chart.Axis',
43027
43028     requires: ['Ext.draw.Draw'],
43029
43030     
43031
43032     
43033
43034     
43035
43036     
43037
43038     
43039
43040     //@private force min/max values from store
43041
43042     forceMinMax: false,
43043
43044     
43045     dashSize: 3,
43046
43047     
43048     position: 'bottom',
43049
43050     
43051     skipFirst: false,
43052
43053     
43054     length: 0,
43055
43056     
43057     width: 0,
43058
43059     majorTickSteps: false,
43060
43061     
43062     applyData: Ext.emptyFn,
43063
43064     getRange: function () {
43065         var me = this,
43066             store = me.chart.getChartStore(),
43067             fields = me.fields,
43068             ln = fields.length,
43069             math = Math,
43070             mmax = math.max,
43071             mmin = math.min,
43072             aggregate = false,
43073             min = isNaN(me.minimum) ? Infinity : me.minimum,
43074             max = isNaN(me.maximum) ? -Infinity : me.maximum,
43075             total = 0, i, l, value, values, rec,
43076             excludes = [],
43077             series = me.chart.series.items;
43078
43079         
43080         
43081         
43082         
43083         
43084         
43085         
43086         
43087         for (i = 0, l = series.length; !aggregate && i < l; i++) {
43088             aggregate = aggregate || series[i].stacked;
43089             excludes = series[i].__excludes || excludes;
43090         }
43091         store.each(function(record) {
43092             if (aggregate) {
43093                 if (!isFinite(min)) {
43094                     min = 0;
43095                 }
43096                 for (values = [0, 0], i = 0; i < ln; i++) {
43097                     if (excludes[i]) {
43098                         continue;
43099                     }
43100                     rec = record.get(fields[i]);
43101                     values[+(rec > 0)] += math.abs(rec);
43102                 }
43103                 max = mmax(max, -values[0], +values[1]);
43104                 min = mmin(min, -values[0], +values[1]);
43105             }
43106             else {
43107                 for (i = 0; i < ln; i++) {
43108                     if (excludes[i]) {
43109                         continue;
43110                     }
43111                     value = record.get(fields[i]);
43112                     max = mmax(max, +value);
43113                     min = mmin(min, +value);
43114                 }
43115             }
43116         });
43117         if (!isFinite(max)) {
43118             max = me.prevMax || 0;
43119         }
43120         if (!isFinite(min)) {
43121             min = me.prevMin || 0;
43122         }
43123         
43124         if (min != max && (max != Math.floor(max))) {
43125             max = Math.floor(max) + 1;
43126         }
43127
43128         if (!isNaN(me.minimum)) {
43129             min = me.minimum;
43130         }
43131         
43132         if (!isNaN(me.maximum)) {
43133             max = me.maximum;
43134         }
43135
43136         return {min: min, max: max};
43137     },
43138
43139     
43140     calcEnds: function() {
43141         var me = this,
43142             fields = me.fields,
43143             range = me.getRange(),
43144             min = range.min,
43145             max = range.max,
43146             outfrom, outto, out;
43147
43148         out = Ext.draw.Draw.snapEnds(min, max, me.majorTickSteps !== false ?  (me.majorTickSteps +1) : me.steps);
43149         outfrom = out.from;
43150         outto = out.to;
43151         if (me.forceMinMax) {
43152             if (!isNaN(max)) {
43153                 out.to = max;
43154             }
43155             if (!isNaN(min)) {
43156                 out.from = min;
43157             }
43158         }
43159         if (!isNaN(me.maximum)) {
43160             
43161             
43162             out.to = me.maximum;
43163         }
43164         if (!isNaN(me.minimum)) {
43165             
43166             
43167             out.from = me.minimum;
43168         }
43169
43170         
43171         out.step = (out.to - out.from) / (outto - outfrom) * out.step;
43172
43173         if (me.adjustMaximumByMajorUnit) {
43174             out.to += out.step;
43175         }
43176         if (me.adjustMinimumByMajorUnit) {
43177             out.from -= out.step;
43178         }
43179         me.prevMin = min == max? 0 : min;
43180         me.prevMax = max;
43181         return out;
43182     },
43183
43184     
43185     drawAxis: function (init) {
43186         var me = this,
43187             i, j,
43188             x = me.x,
43189             y = me.y,
43190             gutterX = me.chart.maxGutter[0],
43191             gutterY = me.chart.maxGutter[1],
43192             dashSize = me.dashSize,
43193             subDashesX = me.minorTickSteps || 0,
43194             subDashesY = me.minorTickSteps || 0,
43195             length = me.length,
43196             position = me.position,
43197             inflections = [],
43198             calcLabels = false,
43199             stepCalcs = me.applyData(),
43200             step = stepCalcs.step,
43201             steps = stepCalcs.steps,
43202             from = stepCalcs.from,
43203             to = stepCalcs.to,
43204             trueLength,
43205             currentX,
43206             currentY,
43207             path,
43208             prev,
43209             dashesX,
43210             dashesY,
43211             delta;
43212
43213         
43214         
43215         
43216         if (me.hidden || isNaN(step) || (from == to)) {
43217             return;
43218         }
43219
43220         me.from = stepCalcs.from;
43221         me.to = stepCalcs.to;
43222         if (position == 'left' || position == 'right') {
43223             currentX = Math.floor(x) + 0.5;
43224             path = ["M", currentX, y, "l", 0, -length];
43225             trueLength = length - (gutterY * 2);
43226         }
43227         else {
43228             currentY = Math.floor(y) + 0.5;
43229             path = ["M", x, currentY, "l", length, 0];
43230             trueLength = length - (gutterX * 2);
43231         }
43232
43233         delta = trueLength / (steps || 1);
43234         dashesX = Math.max(subDashesX +1, 0);
43235         dashesY = Math.max(subDashesY +1, 0);
43236         if (me.type == 'Numeric' || me.type == 'Time') {
43237             calcLabels = true;
43238             me.labels = [stepCalcs.from];
43239         }
43240         if (position == 'right' || position == 'left') {
43241             currentY = y - gutterY;
43242             currentX = x - ((position == 'left') * dashSize * 2);
43243             while (currentY >= y - gutterY - trueLength) {
43244                 path.push("M", currentX, Math.floor(currentY) + 0.5, "l", dashSize * 2 + 1, 0);
43245                 if (currentY != y - gutterY) {
43246                     for (i = 1; i < dashesY; i++) {
43247                         path.push("M", currentX + dashSize, Math.floor(currentY + delta * i / dashesY) + 0.5, "l", dashSize + 1, 0);
43248                     }
43249                 }
43250                 inflections.push([ Math.floor(x), Math.floor(currentY) ]);
43251                 currentY -= delta;
43252                 if (calcLabels) {
43253                     me.labels.push(me.labels[me.labels.length -1] + step);
43254                 }
43255                 if (delta === 0) {
43256                     break;
43257                 }
43258             }
43259             if (Math.round(currentY + delta - (y - gutterY - trueLength))) {
43260                 path.push("M", currentX, Math.floor(y - length + gutterY) + 0.5, "l", dashSize * 2 + 1, 0);
43261                 for (i = 1; i < dashesY; i++) {
43262                     path.push("M", currentX + dashSize, Math.floor(y - length + gutterY + delta * i / dashesY) + 0.5, "l", dashSize + 1, 0);
43263                 }
43264                 inflections.push([ Math.floor(x), Math.floor(currentY) ]);
43265                 if (calcLabels) {
43266                     me.labels.push(me.labels[me.labels.length -1] + step);
43267                 }
43268             }
43269         } else {
43270             currentX = x + gutterX;
43271             currentY = y - ((position == 'top') * dashSize * 2);
43272             while (currentX <= x + gutterX + trueLength) {
43273                 path.push("M", Math.floor(currentX) + 0.5, currentY, "l", 0, dashSize * 2 + 1);
43274                 if (currentX != x + gutterX) {
43275                     for (i = 1; i < dashesX; i++) {
43276                         path.push("M", Math.floor(currentX - delta * i / dashesX) + 0.5, currentY, "l", 0, dashSize + 1);
43277                     }
43278                 }
43279                 inflections.push([ Math.floor(currentX), Math.floor(y) ]);
43280                 currentX += delta;
43281                 if (calcLabels) {
43282                     me.labels.push(me.labels[me.labels.length -1] + step);
43283                 }
43284                 if (delta === 0) {
43285                     break;
43286                 }
43287             }
43288             if (Math.round(currentX - delta - (x + gutterX + trueLength))) {
43289                 path.push("M", Math.floor(x + length - gutterX) + 0.5, currentY, "l", 0, dashSize * 2 + 1);
43290                 for (i = 1; i < dashesX; i++) {
43291                     path.push("M", Math.floor(x + length - gutterX - delta * i / dashesX) + 0.5, currentY, "l", 0, dashSize + 1);
43292                 }
43293                 inflections.push([ Math.floor(currentX), Math.floor(y) ]);
43294                 if (calcLabels) {
43295                     me.labels.push(me.labels[me.labels.length -1] + step);
43296                 }
43297             }
43298         }
43299         if (!me.axis) {
43300             me.axis = me.chart.surface.add(Ext.apply({
43301                 type: 'path',
43302                 path: path
43303             }, me.axisStyle));
43304         }
43305         me.axis.setAttributes({
43306             path: path
43307         }, true);
43308         me.inflections = inflections;
43309         if (!init && me.grid) {
43310             me.drawGrid();
43311         }
43312         me.axisBBox = me.axis.getBBox();
43313         me.drawLabel();
43314     },
43315
43316     
43317     drawGrid: function() {
43318         var me = this,
43319             surface = me.chart.surface,
43320             grid = me.grid,
43321             odd = grid.odd,
43322             even = grid.even,
43323             inflections = me.inflections,
43324             ln = inflections.length - ((odd || even)? 0 : 1),
43325             position = me.position,
43326             gutter = me.chart.maxGutter,
43327             width = me.width - 2,
43328             vert = false,
43329             point, prevPoint,
43330             i = 1,
43331             path = [], styles, lineWidth, dlineWidth,
43332             oddPath = [], evenPath = [];
43333
43334         if ((gutter[1] !== 0 && (position == 'left' || position == 'right')) ||
43335             (gutter[0] !== 0 && (position == 'top' || position == 'bottom'))) {
43336             i = 0;
43337             ln++;
43338         }
43339         for (; i < ln; i++) {
43340             point = inflections[i];
43341             prevPoint = inflections[i - 1];
43342             if (odd || even) {
43343                 path = (i % 2)? oddPath : evenPath;
43344                 styles = ((i % 2)? odd : even) || {};
43345                 lineWidth = (styles.lineWidth || styles['stroke-width'] || 0) / 2;
43346                 dlineWidth = 2 * lineWidth;
43347                 if (position == 'left') {
43348                     path.push("M", prevPoint[0] + 1 + lineWidth, prevPoint[1] + 0.5 - lineWidth,
43349                               "L", prevPoint[0] + 1 + width - lineWidth, prevPoint[1] + 0.5 - lineWidth,
43350                               "L", point[0] + 1 + width - lineWidth, point[1] + 0.5 + lineWidth,
43351                               "L", point[0] + 1 + lineWidth, point[1] + 0.5 + lineWidth, "Z");
43352                 }
43353                 else if (position == 'right') {
43354                     path.push("M", prevPoint[0] - lineWidth, prevPoint[1] + 0.5 - lineWidth,
43355                               "L", prevPoint[0] - width + lineWidth, prevPoint[1] + 0.5 - lineWidth,
43356                               "L", point[0] - width + lineWidth, point[1] + 0.5 + lineWidth,
43357                               "L", point[0] - lineWidth, point[1] + 0.5 + lineWidth, "Z");
43358                 }
43359                 else if (position == 'top') {
43360                     path.push("M", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] + 1 + lineWidth,
43361                               "L", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] + 1 + width - lineWidth,
43362                               "L", point[0] + 0.5 - lineWidth, point[1] + 1 + width - lineWidth,
43363                               "L", point[0] + 0.5 - lineWidth, point[1] + 1 + lineWidth, "Z");
43364                 }
43365                 else {
43366                     path.push("M", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] - lineWidth,
43367                             "L", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] - width + lineWidth,
43368                             "L", point[0] + 0.5 - lineWidth, point[1] - width + lineWidth,
43369                             "L", point[0] + 0.5 - lineWidth, point[1] - lineWidth, "Z");
43370                 }
43371             } else {
43372                 if (position == 'left') {
43373                     path = path.concat(["M", point[0] + 0.5, point[1] + 0.5, "l", width, 0]);
43374                 }
43375                 else if (position == 'right') {
43376                     path = path.concat(["M", point[0] - 0.5, point[1] + 0.5, "l", -width, 0]);
43377                 }
43378                 else if (position == 'top') {
43379                     path = path.concat(["M", point[0] + 0.5, point[1] + 0.5, "l", 0, width]);
43380                 }
43381                 else {
43382                     path = path.concat(["M", point[0] + 0.5, point[1] - 0.5, "l", 0, -width]);
43383                 }
43384             }
43385         }
43386         if (odd || even) {
43387             if (oddPath.length) {
43388                 if (!me.gridOdd && oddPath.length) {
43389                     me.gridOdd = surface.add({
43390                         type: 'path',
43391                         path: oddPath
43392                     });
43393                 }
43394                 me.gridOdd.setAttributes(Ext.apply({
43395                     path: oddPath,
43396                     hidden: false
43397                 }, odd || {}), true);
43398             }
43399             if (evenPath.length) {
43400                 if (!me.gridEven) {
43401                     me.gridEven = surface.add({
43402                         type: 'path',
43403                         path: evenPath
43404                     });
43405                 }
43406                 me.gridEven.setAttributes(Ext.apply({
43407                     path: evenPath,
43408                     hidden: false
43409                 }, even || {}), true);
43410             }
43411         }
43412         else {
43413             if (path.length) {
43414                 if (!me.gridLines) {
43415                     me.gridLines = me.chart.surface.add({
43416                         type: 'path',
43417                         path: path,
43418                         "stroke-width": me.lineWidth || 1,
43419                         stroke: me.gridColor || '#ccc'
43420                     });
43421                 }
43422                 me.gridLines.setAttributes({
43423                     hidden: false,
43424                     path: path
43425                 }, true);
43426             }
43427             else if (me.gridLines) {
43428                 me.gridLines.hide(true);
43429             }
43430         }
43431     },
43432
43433     //@private
43434
43435     getOrCreateLabel: function(i, text) {
43436         var me = this,
43437             labelGroup = me.labelGroup,
43438             textLabel = labelGroup.getAt(i),
43439             surface = me.chart.surface;
43440         if (textLabel) {
43441             if (text != textLabel.attr.text) {
43442                 textLabel.setAttributes(Ext.apply({
43443                     text: text
43444                 }, me.label), true);
43445                 textLabel._bbox = textLabel.getBBox();
43446             }
43447         }
43448         else {
43449             textLabel = surface.add(Ext.apply({
43450                 group: labelGroup,
43451                 type: 'text',
43452                 x: 0,
43453                 y: 0,
43454                 text: text
43455             }, me.label));
43456             surface.renderItem(textLabel);
43457             textLabel._bbox = textLabel.getBBox();
43458         }
43459         
43460         if (me.label.rotation) {
43461             textLabel.setAttributes({
43462                 rotation: {
43463                     degrees: 0
43464                 }
43465             }, true);
43466             textLabel._ubbox = textLabel.getBBox();
43467             textLabel.setAttributes(me.label, true);
43468         } else {
43469             textLabel._ubbox = textLabel._bbox;
43470         }
43471         return textLabel;
43472     },
43473
43474     rect2pointArray: function(sprite) {
43475         var surface = this.chart.surface,
43476             rect = surface.getBBox(sprite, true),
43477             p1 = [rect.x, rect.y],
43478             p1p = p1.slice(),
43479             p2 = [rect.x + rect.width, rect.y],
43480             p2p = p2.slice(),
43481             p3 = [rect.x + rect.width, rect.y + rect.height],
43482             p3p = p3.slice(),
43483             p4 = [rect.x, rect.y + rect.height],
43484             p4p = p4.slice(),
43485             matrix = sprite.matrix;
43486         
43487         p1[0] = matrix.x.apply(matrix, p1p);
43488         p1[1] = matrix.y.apply(matrix, p1p);
43489
43490         p2[0] = matrix.x.apply(matrix, p2p);
43491         p2[1] = matrix.y.apply(matrix, p2p);
43492
43493         p3[0] = matrix.x.apply(matrix, p3p);
43494         p3[1] = matrix.y.apply(matrix, p3p);
43495
43496         p4[0] = matrix.x.apply(matrix, p4p);
43497         p4[1] = matrix.y.apply(matrix, p4p);
43498         return [p1, p2, p3, p4];
43499     },
43500
43501     intersect: function(l1, l2) {
43502         var r1 = this.rect2pointArray(l1),
43503             r2 = this.rect2pointArray(l2);
43504         return !!Ext.draw.Draw.intersect(r1, r2).length;
43505     },
43506
43507     drawHorizontalLabels: function() {
43508        var  me = this,
43509             labelConf = me.label,
43510             floor = Math.floor,
43511             max = Math.max,
43512             axes = me.chart.axes,
43513             position = me.position,
43514             inflections = me.inflections,
43515             ln = inflections.length,
43516             labels = me.labels,
43517             labelGroup = me.labelGroup,
43518             maxHeight = 0,
43519             ratio,
43520             gutterY = me.chart.maxGutter[1],
43521             ubbox, bbox, point, prevX, prevLabel,
43522             projectedWidth = 0,
43523             textLabel, attr, textRight, text,
43524             label, last, x, y, i, firstLabel;
43525
43526         last = ln - 1;
43527         
43528         point = inflections[0];
43529         firstLabel = me.getOrCreateLabel(0, me.label.renderer(labels[0]));
43530         ratio = Math.floor(Math.abs(Math.sin(labelConf.rotate && (labelConf.rotate.degrees * Math.PI / 180) || 0)));
43531
43532         for (i = 0; i < ln; i++) {
43533             point = inflections[i];
43534             text = me.label.renderer(labels[i]);
43535             textLabel = me.getOrCreateLabel(i, text);
43536             bbox = textLabel._bbox;
43537             maxHeight = max(maxHeight, bbox.height + me.dashSize + me.label.padding);
43538             x = floor(point[0] - (ratio? bbox.height : bbox.width) / 2);
43539             if (me.chart.maxGutter[0] == 0) {
43540                 if (i == 0 && axes.findIndex('position', 'left') == -1) {
43541                     x = point[0];
43542                 }
43543                 else if (i == last && axes.findIndex('position', 'right') == -1) {
43544                     x = point[0] - bbox.width;
43545                 }
43546             }
43547             if (position == 'top') {
43548                 y = point[1] - (me.dashSize * 2) - me.label.padding - (bbox.height / 2);
43549             }
43550             else {
43551                 y = point[1] + (me.dashSize * 2) + me.label.padding + (bbox.height / 2);
43552             }
43553
43554             textLabel.setAttributes({
43555                 hidden: false,
43556                 x: x,
43557                 y: y
43558             }, true);
43559
43560             
43561             if (i != 0 && (me.intersect(textLabel, prevLabel)
43562                 || me.intersect(textLabel, firstLabel))) {
43563                 textLabel.hide(true);
43564                 continue;
43565             }
43566
43567             prevLabel = textLabel;
43568         }
43569
43570         return maxHeight;
43571     },
43572
43573     drawVerticalLabels: function() {
43574         var me = this,
43575             inflections = me.inflections,
43576             position = me.position,
43577             ln = inflections.length,
43578             labels = me.labels,
43579             maxWidth = 0,
43580             max = Math.max,
43581             floor = Math.floor,
43582             ceil = Math.ceil,
43583             axes = me.chart.axes,
43584             gutterY = me.chart.maxGutter[1],
43585             ubbox, bbox, point, prevLabel,
43586             projectedWidth = 0,
43587             textLabel, attr, textRight, text,
43588             label, last, x, y, i;
43589
43590         last = ln;
43591         for (i = 0; i < last; i++) {
43592             point = inflections[i];
43593             text = me.label.renderer(labels[i]);
43594             textLabel = me.getOrCreateLabel(i, text);
43595             bbox = textLabel._bbox;
43596
43597             maxWidth = max(maxWidth, bbox.width + me.dashSize + me.label.padding);
43598             y = point[1];
43599             if (gutterY < bbox.height / 2) {
43600                 if (i == last - 1 && axes.findIndex('position', 'top') == -1) {
43601                     y = me.y - me.length + ceil(bbox.height / 2);
43602                 }
43603                 else if (i == 0 && axes.findIndex('position', 'bottom') == -1) {
43604                     y = me.y - floor(bbox.height / 2);
43605                 }
43606             }
43607             if (position == 'left') {
43608                 x = point[0] - bbox.width - me.dashSize - me.label.padding - 2;
43609             }
43610             else {
43611                 x = point[0] + me.dashSize + me.label.padding + 2;
43612             }
43613             textLabel.setAttributes(Ext.apply({
43614                 hidden: false,
43615                 x: x,
43616                 y: y
43617             }, me.label), true);
43618             
43619             if (i != 0 && me.intersect(textLabel, prevLabel)) {
43620                 textLabel.hide(true);
43621                 continue;
43622             }
43623             prevLabel = textLabel;
43624         }
43625
43626         return maxWidth;
43627     },
43628
43629     
43630     drawLabel: function() {
43631         var me = this,
43632             position = me.position,
43633             labelGroup = me.labelGroup,
43634             inflections = me.inflections,
43635             maxWidth = 0,
43636             maxHeight = 0,
43637             ln, i;
43638
43639         if (position == 'left' || position == 'right') {
43640             maxWidth = me.drawVerticalLabels();
43641         } else {
43642             maxHeight = me.drawHorizontalLabels();
43643         }
43644
43645         
43646         ln = labelGroup.getCount();
43647         i = inflections.length;
43648         for (; i < ln; i++) {
43649             labelGroup.getAt(i).hide(true);
43650         }
43651
43652         me.bbox = {};
43653         Ext.apply(me.bbox, me.axisBBox);
43654         me.bbox.height = maxHeight;
43655         me.bbox.width = maxWidth;
43656         if (Ext.isString(me.title)) {
43657             me.drawTitle(maxWidth, maxHeight);
43658         }
43659     },
43660
43661     
43662     elipsis: function(sprite, text, desiredWidth, minWidth, center) {
43663         var bbox,
43664             x;
43665
43666         if (desiredWidth < minWidth) {
43667             sprite.hide(true);
43668             return false;
43669         }
43670         while (text.length > 4) {
43671             text = text.substr(0, text.length - 4) + "...";
43672             sprite.setAttributes({
43673                 text: text
43674             }, true);
43675             bbox = sprite.getBBox();
43676             if (bbox.width < desiredWidth) {
43677                 if (typeof center == 'number') {
43678                     sprite.setAttributes({
43679                         x: Math.floor(center - (bbox.width / 2))
43680                     }, true);
43681                 }
43682                 break;
43683             }
43684         }
43685         return true;
43686     },
43687
43688     
43689     setTitle: function(title) {
43690         this.title = title;
43691         this.drawLabel();
43692     },
43693
43694     
43695     drawTitle: function(maxWidth, maxHeight) {
43696         var me = this,
43697             position = me.position,
43698             surface = me.chart.surface,
43699             displaySprite = me.displaySprite,
43700             title = me.title,
43701             rotate = (position == 'left' || position == 'right'),
43702             x = me.x,
43703             y = me.y,
43704             base, bbox, pad;
43705
43706         if (displaySprite) {
43707             displaySprite.setAttributes({text: title}, true);
43708         } else {
43709             base = {
43710                 type: 'text',
43711                 x: 0,
43712                 y: 0,
43713                 text: title
43714             };
43715             displaySprite = me.displaySprite = surface.add(Ext.apply(base, me.axisTitleStyle, me.labelTitle));
43716             surface.renderItem(displaySprite);
43717         }
43718         bbox = displaySprite.getBBox();
43719         pad = me.dashSize + me.label.padding;
43720
43721         if (rotate) {
43722             y -= ((me.length / 2) - (bbox.height / 2));
43723             if (position == 'left') {
43724                 x -= (maxWidth + pad + (bbox.width / 2));
43725             }
43726             else {
43727                 x += (maxWidth + pad + bbox.width - (bbox.width / 2));
43728             }
43729             me.bbox.width += bbox.width + 10;
43730         }
43731         else {
43732             x += (me.length / 2) - (bbox.width * 0.5);
43733             if (position == 'top') {
43734                 y -= (maxHeight + pad + (bbox.height * 0.3));
43735             }
43736             else {
43737                 y += (maxHeight + pad + (bbox.height * 0.8));
43738             }
43739             me.bbox.height += bbox.height + 10;
43740         }
43741         displaySprite.setAttributes({
43742             translate: {
43743                 x: x,
43744                 y: y
43745             }
43746         }, true);
43747     }
43748 });
43749
43750
43751 Ext.define('Ext.chart.axis.Category', {
43752
43753     
43754
43755     extend: 'Ext.chart.axis.Axis',
43756
43757     alternateClassName: 'Ext.chart.CategoryAxis',
43758
43759     alias: 'axis.category',
43760
43761     
43762
43763     
43764     categoryNames: null,
43765
43766     
43767     calculateCategoryCount: false,
43768
43769     
43770     setLabels: function() {
43771         var store = this.chart.store,
43772             fields = this.fields,
43773             ln = fields.length,
43774             i;
43775
43776         this.labels = [];
43777         store.each(function(record) {
43778             for (i = 0; i < ln; i++) {
43779                 this.labels.push(record.get(fields[i]));
43780             }
43781         }, this);
43782     },
43783
43784     
43785     applyData: function() {
43786         this.callParent();
43787         this.setLabels();
43788         var count = this.chart.store.getCount();
43789         return {
43790             from: 0,
43791             to: count,
43792             power: 1,
43793             step: 1,
43794             steps: count - 1
43795         };
43796     }
43797 });
43798
43799
43800 Ext.define('Ext.chart.axis.Gauge', {
43801
43802     
43803
43804     extend: 'Ext.chart.axis.Abstract',
43805
43806     
43807
43808     
43809
43810     
43811
43812     
43813
43814     
43815
43816     
43817
43818     position: 'gauge',
43819
43820     alias: 'axis.gauge',
43821
43822     drawAxis: function(init) {
43823         var chart = this.chart,
43824             surface = chart.surface,
43825             bbox = chart.chartBBox,
43826             centerX = bbox.x + (bbox.width / 2),
43827             centerY = bbox.y + bbox.height,
43828             margin = this.margin || 10,
43829             rho = Math.min(bbox.width, 2 * bbox.height) /2 + margin,
43830             sprites = [], sprite,
43831             steps = this.steps,
43832             i, pi = Math.PI,
43833             cos = Math.cos,
43834             sin = Math.sin;
43835
43836         if (this.sprites && !chart.resizing) {
43837             this.drawLabel();
43838             return;
43839         }
43840
43841         if (this.margin >= 0) {
43842             if (!this.sprites) {
43843                 
43844                 for (i = 0; i <= steps; i++) {
43845                     sprite = surface.add({
43846                         type: 'path',
43847                         path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi),
43848                                     centerY + (rho - margin) * sin(i / steps * pi - pi),
43849                                     'L', centerX + rho * cos(i / steps * pi - pi),
43850                                     centerY + rho * sin(i / steps * pi - pi), 'Z'],
43851                         stroke: '#ccc'
43852                     });
43853                     sprite.setAttributes({
43854                         hidden: false
43855                     }, true);
43856                     sprites.push(sprite);
43857                 }
43858             } else {
43859                 sprites = this.sprites;
43860                 
43861                 for (i = 0; i <= steps; i++) {
43862                     sprites[i].setAttributes({
43863                         path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi),
43864                                     centerY + (rho - margin) * sin(i / steps * pi - pi),
43865                                'L', centerX + rho * cos(i / steps * pi - pi),
43866                                     centerY + rho * sin(i / steps * pi - pi), 'Z'],
43867                         stroke: '#ccc'
43868                     }, true);
43869                 }
43870             }
43871         }
43872         this.sprites = sprites;
43873         this.drawLabel();
43874         if (this.title) {
43875             this.drawTitle();
43876         }
43877     },
43878
43879     drawTitle: function() {
43880         var me = this,
43881             chart = me.chart,
43882             surface = chart.surface,
43883             bbox = chart.chartBBox,
43884             labelSprite = me.titleSprite,
43885             labelBBox;
43886
43887         if (!labelSprite) {
43888             me.titleSprite = labelSprite = surface.add({
43889                 type: 'text',
43890                 zIndex: 2
43891             });
43892         }
43893         labelSprite.setAttributes(Ext.apply({
43894             text: me.title
43895         }, me.label || {}), true);
43896         labelBBox = labelSprite.getBBox();
43897         labelSprite.setAttributes({
43898             x: bbox.x + (bbox.width / 2) - (labelBBox.width / 2),
43899             y: bbox.y + bbox.height - (labelBBox.height / 2) - 4
43900         }, true);
43901     },
43902
43903     
43904     setTitle: function(title) {
43905         this.title = title;
43906         this.drawTitle();
43907     },
43908
43909     drawLabel: function() {
43910         var chart = this.chart,
43911             surface = chart.surface,
43912             bbox = chart.chartBBox,
43913             centerX = bbox.x + (bbox.width / 2),
43914             centerY = bbox.y + bbox.height,
43915             margin = this.margin || 10,
43916             rho = Math.min(bbox.width, 2 * bbox.height) /2 + 2 * margin,
43917             round = Math.round,
43918             labelArray = [], label,
43919             maxValue = this.maximum || 0,
43920             steps = this.steps, i = 0,
43921             adjY,
43922             pi = Math.PI,
43923             cos = Math.cos,
43924             sin = Math.sin,
43925             labelConf = this.label,
43926             renderer = labelConf.renderer || function(v) { return v; };
43927
43928         if (!this.labelArray) {
43929             
43930             for (i = 0; i <= steps; i++) {
43931                 
43932                 adjY = (i === 0 || i === steps) ? 7 : 0;
43933                 label = surface.add({
43934                     type: 'text',
43935                     text: renderer(round(i / steps * maxValue)),
43936                     x: centerX + rho * cos(i / steps * pi - pi),
43937                     y: centerY + rho * sin(i / steps * pi - pi) - adjY,
43938                     'text-anchor': 'middle',
43939                     'stroke-width': 0.2,
43940                     zIndex: 10,
43941                     stroke: '#333'
43942                 });
43943                 label.setAttributes({
43944                     hidden: false
43945                 }, true);
43946                 labelArray.push(label);
43947             }
43948         }
43949         else {
43950             labelArray = this.labelArray;
43951             
43952             for (i = 0; i <= steps; i++) {
43953                 
43954                 adjY = (i === 0 || i === steps) ? 7 : 0;
43955                 labelArray[i].setAttributes({
43956                     text: renderer(round(i / steps * maxValue)),
43957                     x: centerX + rho * cos(i / steps * pi - pi),
43958                     y: centerY + rho * sin(i / steps * pi - pi) - adjY
43959                 }, true);
43960             }
43961         }
43962         this.labelArray = labelArray;
43963     }
43964 });
43965
43966 Ext.define('Ext.chart.axis.Numeric', {
43967
43968     
43969
43970     extend: 'Ext.chart.axis.Axis',
43971
43972     alternateClassName: 'Ext.chart.NumericAxis',
43973
43974     
43975
43976     type: 'numeric',
43977
43978     alias: 'axis.numeric',
43979
43980     constructor: function(config) {
43981         var me = this,
43982             hasLabel = !!(config.label && config.label.renderer),
43983             label;
43984
43985         me.callParent([config]);
43986         label = me.label;
43987         if (me.roundToDecimal === false) {
43988             return;
43989         }
43990         if (!hasLabel) {
43991             label.renderer = function(v) {
43992                 return me.roundToDecimal(v, me.decimals);
43993             };
43994         }
43995     },
43996
43997     roundToDecimal: function(v, dec) {
43998         var val = Math.pow(10, dec || 0);
43999         return Math.floor(v * val) / val;
44000     },
44001
44002     
44003     minimum: NaN,
44004
44005     
44006     maximum: NaN,
44007
44008     
44009     decimals: 2,
44010
44011     
44012     scale: "linear",
44013
44014     
44015     position: 'left',
44016
44017     
44018     adjustMaximumByMajorUnit: false,
44019
44020     
44021     adjustMinimumByMajorUnit: false,
44022
44023     
44024     applyData: function() {
44025         this.callParent();
44026         return this.calcEnds();
44027     }
44028 });
44029
44030
44031 Ext.define('Ext.chart.axis.Radial', {
44032
44033     
44034
44035     extend: 'Ext.chart.axis.Abstract',
44036
44037     
44038
44039     position: 'radial',
44040
44041     alias: 'axis.radial',
44042
44043     drawAxis: function(init) {
44044         var chart = this.chart,
44045             surface = chart.surface,
44046             bbox = chart.chartBBox,
44047             store = chart.store,
44048             l = store.getCount(),
44049             centerX = bbox.x + (bbox.width / 2),
44050             centerY = bbox.y + (bbox.height / 2),
44051             rho = Math.min(bbox.width, bbox.height) /2,
44052             sprites = [], sprite,
44053             steps = this.steps,
44054             i, j, pi2 = Math.PI * 2,
44055             cos = Math.cos, sin = Math.sin;
44056
44057         if (this.sprites && !chart.resizing) {
44058             this.drawLabel();
44059             return;
44060         }
44061
44062         if (!this.sprites) {
44063             
44064             for (i = 1; i <= steps; i++) {
44065                 sprite = surface.add({
44066                     type: 'circle',
44067                     x: centerX,
44068                     y: centerY,
44069                     radius: Math.max(rho * i / steps, 0),
44070                     stroke: '#ccc'
44071                 });
44072                 sprite.setAttributes({
44073                     hidden: false
44074                 }, true);
44075                 sprites.push(sprite);
44076             }
44077             
44078             store.each(function(rec, i) {
44079                 sprite = surface.add({
44080                     type: 'path',
44081                     path: ['M', centerX, centerY, 'L', centerX + rho * cos(i / l * pi2), centerY + rho * sin(i / l * pi2), 'Z'],
44082                     stroke: '#ccc'
44083                 });
44084                 sprite.setAttributes({
44085                     hidden: false
44086                 }, true);
44087                 sprites.push(sprite);
44088             });
44089         } else {
44090             sprites = this.sprites;
44091             
44092             for (i = 0; i < steps; i++) {
44093                 sprites[i].setAttributes({
44094                     x: centerX,
44095                     y: centerY,
44096                     radius: Math.max(rho * (i + 1) / steps, 0),
44097                     stroke: '#ccc'
44098                 }, true);
44099             }
44100             
44101             store.each(function(rec, j) {
44102                 sprites[i + j].setAttributes({
44103                     path: ['M', centerX, centerY, 'L', centerX + rho * cos(j / l * pi2), centerY + rho * sin(j / l * pi2), 'Z'],
44104                     stroke: '#ccc'
44105                 }, true);
44106             });
44107         }
44108         this.sprites = sprites;
44109
44110         this.drawLabel();
44111     },
44112
44113     drawLabel: function() {
44114         var chart = this.chart,
44115             surface = chart.surface,
44116             bbox = chart.chartBBox,
44117             store = chart.store,
44118             centerX = bbox.x + (bbox.width / 2),
44119             centerY = bbox.y + (bbox.height / 2),
44120             rho = Math.min(bbox.width, bbox.height) /2,
44121             max = Math.max, round = Math.round,
44122             labelArray = [], label,
44123             fields = [], nfields,
44124             categories = [], xField,
44125             aggregate = !this.maximum,
44126             maxValue = this.maximum || 0,
44127             steps = this.steps, i = 0, j, dx, dy,
44128             pi2 = Math.PI * 2,
44129             cos = Math.cos, sin = Math.sin,
44130             display = this.label.display,
44131             draw = display !== 'none',
44132             margin = 10;
44133
44134         if (!draw) {
44135             return;
44136         }
44137
44138         
44139         chart.series.each(function(series) {
44140             fields.push(series.yField);
44141             xField = series.xField;
44142         });
44143         
44144         
44145         store.each(function(record, i) {
44146             if (aggregate) {
44147                 for (i = 0, nfields = fields.length; i < nfields; i++) {
44148                     maxValue = max(+record.get(fields[i]), maxValue);
44149                 }
44150             }
44151             categories.push(record.get(xField));
44152         });
44153         if (!this.labelArray) {
44154             if (display != 'categories') {
44155                 
44156                 for (i = 1; i <= steps; i++) {
44157                     label = surface.add({
44158                         type: 'text',
44159                         text: round(i / steps * maxValue),
44160                         x: centerX,
44161                         y: centerY - rho * i / steps,
44162                         'text-anchor': 'middle',
44163                         'stroke-width': 0.1,
44164                         stroke: '#333'
44165                     });
44166                     label.setAttributes({
44167                         hidden: false
44168                     }, true);
44169                     labelArray.push(label);
44170                 }
44171             }
44172             if (display != 'scale') {
44173                 
44174                 for (j = 0, steps = categories.length; j < steps; j++) {
44175                     dx = cos(j / steps * pi2) * (rho + margin);
44176                     dy = sin(j / steps * pi2) * (rho + margin);
44177                     label = surface.add({
44178                         type: 'text',
44179                         text: categories[j],
44180                         x: centerX + dx,
44181                         y: centerY + dy,
44182                         'text-anchor': dx * dx <= 0.001? 'middle' : (dx < 0? 'end' : 'start')
44183                     });
44184                     label.setAttributes({
44185                         hidden: false
44186                     }, true);
44187                     labelArray.push(label);
44188                 }
44189             }
44190         }
44191         else {
44192             labelArray = this.labelArray;
44193             if (display != 'categories') {
44194                 
44195                 for (i = 0; i < steps; i++) {
44196                     labelArray[i].setAttributes({
44197                         text: round((i + 1) / steps * maxValue),
44198                         x: centerX,
44199                         y: centerY - rho * (i + 1) / steps,
44200                         'text-anchor': 'middle',
44201                         'stroke-width': 0.1,
44202                         stroke: '#333'
44203                     }, true);
44204                 }
44205             }
44206             if (display != 'scale') {
44207                 
44208                 for (j = 0, steps = categories.length; j < steps; j++) {
44209                     dx = cos(j / steps * pi2) * (rho + margin);
44210                     dy = sin(j / steps * pi2) * (rho + margin);
44211                     if (labelArray[i + j]) {
44212                         labelArray[i + j].setAttributes({
44213                             type: 'text',
44214                             text: categories[j],
44215                             x: centerX + dx,
44216                             y: centerY + dy,
44217                             'text-anchor': dx * dx <= 0.001? 'middle' : (dx < 0? 'end' : 'start')
44218                         }, true);
44219                     }
44220                 }
44221             }
44222         }
44223         this.labelArray = labelArray;
44224     }
44225 });
44226
44227 Ext.define('Ext.data.AbstractStore', {
44228     requires: ['Ext.util.MixedCollection', 'Ext.data.Operation', 'Ext.util.Filter'],
44229     
44230     mixins: {
44231         observable: 'Ext.util.Observable',
44232         sortable: 'Ext.util.Sortable'
44233     },
44234     
44235     statics: {
44236         create: function(store){
44237             if (!store.isStore) {
44238                 if (!store.type) {
44239                     store.type = 'store';
44240                 }
44241                 store = Ext.createByAlias('store.' + store.type, store);
44242             }
44243             return store;
44244         }    
44245     },
44246     
44247     remoteSort  : false,
44248     remoteFilter: false,
44249
44250     
44251
44252     
44253     autoLoad: false,
44254
44255     
44256     autoSync: false,
44257
44258     
44259     batchUpdateMode: 'operation',
44260
44261     
44262     filterOnLoad: true,
44263
44264     
44265     sortOnLoad: true,
44266
44267     
44268     implicitModel: false,
44269
44270     
44271     defaultProxyType: 'memory',
44272
44273     
44274     isDestroyed: false,
44275
44276     isStore: true,
44277
44278     
44279     
44280     
44281
44282     
44283
44284     sortRoot: 'data',
44285     
44286     
44287     constructor: function(config) {
44288         var me = this,
44289             filters;
44290         
44291         me.addEvents(
44292             
44293             'add',
44294
44295             
44296             'remove',
44297             
44298             
44299             'update',
44300
44301             
44302             'datachanged',
44303
44304             
44305             'beforeload',
44306
44307             
44308             'load',
44309             
44310             
44311             'write',
44312
44313             
44314             'beforesync',
44315             
44316             'clear'
44317         );
44318         
44319         Ext.apply(me, config);
44320         
44321
44322         
44323         me.removed = [];
44324
44325         me.mixins.observable.constructor.apply(me, arguments);
44326         me.model = Ext.ModelManager.getModel(me.model);
44327
44328         
44329         Ext.applyIf(me, {
44330             modelDefaults: {}
44331         });
44332
44333         
44334         if (!me.model && me.fields) {
44335             me.model = Ext.define('Ext.data.Store.ImplicitModel-' + (me.storeId || Ext.id()), {
44336                 extend: 'Ext.data.Model',
44337                 fields: me.fields,
44338                 proxy: me.proxy || me.defaultProxyType
44339             });
44340
44341             delete me.fields;
44342
44343             me.implicitModel = true;
44344         }
44345         
44346
44347         
44348         me.setProxy(me.proxy || me.model.getProxy());
44349
44350         if (me.id && !me.storeId) {
44351             me.storeId = me.id;
44352             delete me.id;
44353         }
44354
44355         if (me.storeId) {
44356             Ext.data.StoreManager.register(me);
44357         }
44358         
44359         me.mixins.sortable.initSortable.call(me);        
44360         
44361         
44362         filters = me.decodeFilters(me.filters);
44363         me.filters = Ext.create('Ext.util.MixedCollection');
44364         me.filters.addAll(filters);
44365     },
44366
44367     
44368     setProxy: function(proxy) {
44369         var me = this;
44370         
44371         if (proxy instanceof Ext.data.proxy.Proxy) {
44372             proxy.setModel(me.model);
44373         } else {
44374             if (Ext.isString(proxy)) {
44375                 proxy = {
44376                     type: proxy    
44377                 };
44378             }
44379             Ext.applyIf(proxy, {
44380                 model: me.model
44381             });
44382             
44383             proxy = Ext.createByAlias('proxy.' + proxy.type, proxy);
44384         }
44385         
44386         me.proxy = proxy;
44387         
44388         return me.proxy;
44389     },
44390
44391     
44392     getProxy: function() {
44393         return this.proxy;
44394     },
44395
44396     
44397     create: function(data, options) {
44398         var me = this,
44399             instance = Ext.ModelManager.create(Ext.applyIf(data, me.modelDefaults), me.model.modelName),
44400             operation;
44401         
44402         options = options || {};
44403
44404         Ext.applyIf(options, {
44405             action : 'create',
44406             records: [instance]
44407         });
44408
44409         operation = Ext.create('Ext.data.Operation', options);
44410
44411         me.proxy.create(operation, me.onProxyWrite, me);
44412         
44413         return instance;
44414     },
44415
44416     read: function() {
44417         return this.load.apply(this, arguments);
44418     },
44419
44420     onProxyRead: Ext.emptyFn,
44421
44422     update: function(options) {
44423         var me = this,
44424             operation;
44425         options = options || {};
44426
44427         Ext.applyIf(options, {
44428             action : 'update',
44429             records: me.getUpdatedRecords()
44430         });
44431
44432         operation = Ext.create('Ext.data.Operation', options);
44433
44434         return me.proxy.update(operation, me.onProxyWrite, me);
44435     },
44436
44437     
44438     onProxyWrite: function(operation) {
44439         var me = this,
44440             success = operation.wasSuccessful(),
44441             records = operation.getRecords();
44442
44443         switch (operation.action) {
44444             case 'create':
44445                 me.onCreateRecords(records, operation, success);
44446                 break;
44447             case 'update':
44448                 me.onUpdateRecords(records, operation, success);
44449                 break;
44450             case 'destroy':
44451                 me.onDestroyRecords(records, operation, success);
44452                 break;
44453         }
44454
44455         if (success) {
44456             me.fireEvent('write', me, operation);
44457             me.fireEvent('datachanged', me);
44458         }
44459         
44460         Ext.callback(operation.callback, operation.scope || me, [records, operation, success]);
44461     },
44462
44463
44464     
44465     destroy: function(options) {
44466         var me = this,
44467             operation;
44468             
44469         options = options || {};
44470
44471         Ext.applyIf(options, {
44472             action : 'destroy',
44473             records: me.getRemovedRecords()
44474         });
44475
44476         operation = Ext.create('Ext.data.Operation', options);
44477
44478         return me.proxy.destroy(operation, me.onProxyWrite, me);
44479     },
44480
44481     
44482     onBatchOperationComplete: function(batch, operation) {
44483         return this.onProxyWrite(operation);
44484     },
44485
44486     
44487     onBatchComplete: function(batch, operation) {
44488         var me = this,
44489             operations = batch.operations,
44490             length = operations.length,
44491             i;
44492
44493         me.suspendEvents();
44494
44495         for (i = 0; i < length; i++) {
44496             me.onProxyWrite(operations[i]);
44497         }
44498
44499         me.resumeEvents();
44500
44501         me.fireEvent('datachanged', me);
44502     },
44503
44504     onBatchException: function(batch, operation) {
44505         
44506         
44507         
44508         
44509         
44510     },
44511
44512     
44513     filterNew: function(item) {
44514         
44515         return item.phantom === true && item.isValid();
44516     },
44517
44518     
44519     getNewRecords: function() {
44520         return [];
44521     },
44522
44523     
44524     getUpdatedRecords: function() {
44525         return [];
44526     },
44527
44528     
44529     filterUpdated: function(item) {
44530         
44531         return item.dirty === true && item.phantom !== true && item.isValid();
44532     },
44533
44534     
44535     getRemovedRecords: function() {
44536         return this.removed;
44537     },
44538
44539     filter: function(filters, value) {
44540
44541     },
44542
44543     
44544     decodeFilters: function(filters) {
44545         if (!Ext.isArray(filters)) {
44546             if (filters === undefined) {
44547                 filters = [];
44548             } else {
44549                 filters = [filters];
44550             }
44551         }
44552
44553         var length = filters.length,
44554             Filter = Ext.util.Filter,
44555             config, i;
44556
44557         for (i = 0; i < length; i++) {
44558             config = filters[i];
44559
44560             if (!(config instanceof Filter)) {
44561                 Ext.apply(config, {
44562                     root: 'data'
44563                 });
44564
44565                 
44566                 if (config.fn) {
44567                     config.filterFn = config.fn;
44568                 }
44569
44570                 
44571                 if (typeof config == 'function') {
44572                     config = {
44573                         filterFn: config
44574                     };
44575                 }
44576
44577                 filters[i] = new Filter(config);
44578             }
44579         }
44580
44581         return filters;
44582     },
44583
44584     clearFilter: function(supressEvent) {
44585
44586     },
44587
44588     isFiltered: function() {
44589
44590     },
44591
44592     filterBy: function(fn, scope) {
44593
44594     },
44595     
44596     
44597     sync: function() {
44598         var me        = this,
44599             options   = {},
44600             toCreate  = me.getNewRecords(),
44601             toUpdate  = me.getUpdatedRecords(),
44602             toDestroy = me.getRemovedRecords(),
44603             needsSync = false;
44604
44605         if (toCreate.length > 0) {
44606             options.create = toCreate;
44607             needsSync = true;
44608         }
44609
44610         if (toUpdate.length > 0) {
44611             options.update = toUpdate;
44612             needsSync = true;
44613         }
44614
44615         if (toDestroy.length > 0) {
44616             options.destroy = toDestroy;
44617             needsSync = true;
44618         }
44619
44620         if (needsSync && me.fireEvent('beforesync', options) !== false) {
44621             me.proxy.batch(options, me.getBatchListeners());
44622         }
44623     },
44624
44625
44626     
44627     getBatchListeners: function() {
44628         var me = this,
44629             listeners = {
44630                 scope: me,
44631                 exception: me.onBatchException
44632             };
44633
44634         if (me.batchUpdateMode == 'operation') {
44635             listeners.operationcomplete = me.onBatchOperationComplete;
44636         } else {
44637             listeners.complete = me.onBatchComplete;
44638         }
44639
44640         return listeners;
44641     },
44642
44643     
44644     save: function() {
44645         return this.sync.apply(this, arguments);
44646     },
44647
44648     
44649     load: function(options) {
44650         var me = this,
44651             operation;
44652
44653         options = options || {};
44654
44655         Ext.applyIf(options, {
44656             action : 'read',
44657             filters: me.filters.items,
44658             sorters: me.getSorters()
44659         });
44660         
44661         operation = Ext.create('Ext.data.Operation', options);
44662
44663         if (me.fireEvent('beforeload', me, operation) !== false) {
44664             me.loading = true;
44665             me.proxy.read(operation, me.onProxyLoad, me);
44666         }
44667         
44668         return me;
44669     },
44670
44671     
44672     afterEdit : function(record) {
44673         var me = this;
44674         
44675         if (me.autoSync) {
44676             me.sync();
44677         }
44678         
44679         me.fireEvent('update', me, record, Ext.data.Model.EDIT);
44680     },
44681
44682     
44683     afterReject : function(record) {
44684         this.fireEvent('update', this, record, Ext.data.Model.REJECT);
44685     },
44686
44687     
44688     afterCommit : function(record) {
44689         this.fireEvent('update', this, record, Ext.data.Model.COMMIT);
44690     },
44691
44692     clearData: Ext.emptyFn,
44693
44694     destroyStore: function() {
44695         var me = this;
44696         
44697         if (!me.isDestroyed) {
44698             if (me.storeId) {
44699                 Ext.data.StoreManager.unregister(me);
44700             }
44701             me.clearData();
44702             me.data = null;
44703             me.tree = null;
44704             
44705             me.reader = me.writer = null;
44706             me.clearListeners();
44707             me.isDestroyed = true;
44708
44709             if (me.implicitModel) {
44710                 Ext.destroy(me.model);
44711             }
44712         }
44713     },
44714     
44715     doSort: function(sorterFn) {
44716         var me = this;
44717         if (me.remoteSort) {
44718             
44719             me.load();
44720         } else {
44721             me.data.sortBy(sorterFn);
44722             me.fireEvent('datachanged', me);
44723         }
44724     },
44725
44726     getCount: Ext.emptyFn,
44727
44728     getById: Ext.emptyFn,
44729     
44730     
44731     removeAll: Ext.emptyFn,
44732     
44733     
44734
44735     
44736     isLoading: function() {
44737         return !!this.loading;
44738      }
44739 });
44740
44741
44742  
44743 Ext.define('Ext.util.Grouper', {
44744
44745     
44746
44747     extend: 'Ext.util.Sorter',
44748
44749     
44750
44751     
44752     getGroupString: function(instance) {
44753         return instance.get(this.property);
44754     }
44755 });
44756
44757 Ext.define('Ext.data.Store', {
44758     extend: 'Ext.data.AbstractStore',
44759
44760     alias: 'store.store',
44761
44762     requires: ['Ext.data.StoreManager', 'Ext.ModelManager', 'Ext.data.Model', 'Ext.util.Grouper'],
44763     uses: ['Ext.data.proxy.Memory'],
44764
44765     
44766     remoteSort: false,
44767
44768     
44769     remoteFilter: false,
44770
44771     
44772     remoteGroup : false,
44773
44774     
44775
44776     
44777
44778     
44779     groupField: undefined,
44780
44781     
44782     groupDir: "ASC",
44783
44784     
44785     pageSize: 25,
44786
44787     
44788     currentPage: 1,
44789
44790     
44791     clearOnPageLoad: true,
44792
44793     
44794     loading: false,
44795
44796     
44797     sortOnFilter: true,
44798
44799     
44800     buffered: false,
44801
44802     
44803     purgePageCount: 5,
44804
44805     isStore: true,
44806
44807     onClassExtended: function(cls, data) {
44808         var model = data.model;
44809
44810         if (typeof model == 'string') {
44811             var onBeforeClassCreated = data.onBeforeClassCreated;
44812
44813             data.onBeforeClassCreated = function(cls, data) {
44814                 var me = this;
44815
44816                 Ext.require(model, function() {
44817                     onBeforeClassCreated.call(me, cls, data);
44818                 });
44819             };
44820         }
44821     },
44822
44823     
44824     constructor: function(config) {
44825         
44826         config = Ext.Object.merge({}, config);
44827
44828         var me = this,
44829             groupers = config.groupers || me.groupers,
44830             groupField = config.groupField || me.groupField,
44831             proxy,
44832             data;
44833
44834         if (config.buffered || me.buffered) {
44835             me.prefetchData = Ext.create('Ext.util.MixedCollection', false, function(record) {
44836                 return record.index;
44837             });
44838             me.pendingRequests = [];
44839             me.pagesRequested = [];
44840
44841             me.sortOnLoad = false;
44842             me.filterOnLoad = false;
44843         }
44844
44845         me.addEvents(
44846             
44847             'beforeprefetch',
44848             
44849             'groupchange',
44850             
44851             'prefetch'
44852         );
44853         data = config.data || me.data;
44854
44855         
44856         me.data = Ext.create('Ext.util.MixedCollection', false, function(record) {
44857             return record.internalId;
44858         });
44859
44860         if (data) {
44861             me.inlineData = data;
44862             delete config.data;
44863         }
44864
44865         if (!groupers && groupField) {
44866             groupers = [{
44867                 property : groupField,
44868                 direction: config.groupDir || me.groupDir
44869             }];
44870         }
44871         delete config.groupers;
44872
44873         
44874         me.groupers = Ext.create('Ext.util.MixedCollection');
44875         me.groupers.addAll(me.decodeGroupers(groupers));
44876
44877         this.callParent([config]);
44878         
44879
44880         if (me.groupers.items.length) {
44881             me.sort(me.groupers.items, 'prepend', false);
44882         }
44883
44884         proxy = me.proxy;
44885         data = me.inlineData;
44886
44887         if (data) {
44888             if (proxy instanceof Ext.data.proxy.Memory) {
44889                 proxy.data = data;
44890                 me.read();
44891             } else {
44892                 me.add.apply(me, data);
44893             }
44894
44895             me.sort();
44896             delete me.inlineData;
44897         } else if (me.autoLoad) {
44898             Ext.defer(me.load, 10, me, [typeof me.autoLoad === 'object' ? me.autoLoad: undefined]);
44899             
44900             
44901         }
44902     },
44903
44904     onBeforeSort: function() {
44905         var groupers = this.groupers;
44906         if (groupers.getCount() > 0) {
44907             this.sort(groupers.items, 'prepend', false);
44908         }
44909     },
44910
44911     
44912     decodeGroupers: function(groupers) {
44913         if (!Ext.isArray(groupers)) {
44914             if (groupers === undefined) {
44915                 groupers = [];
44916             } else {
44917                 groupers = [groupers];
44918             }
44919         }
44920
44921         var length  = groupers.length,
44922             Grouper = Ext.util.Grouper,
44923             config, i;
44924
44925         for (i = 0; i < length; i++) {
44926             config = groupers[i];
44927
44928             if (!(config instanceof Grouper)) {
44929                 if (Ext.isString(config)) {
44930                     config = {
44931                         property: config
44932                     };
44933                 }
44934
44935                 Ext.applyIf(config, {
44936                     root     : 'data',
44937                     direction: "ASC"
44938                 });
44939
44940                 
44941                 if (config.fn) {
44942                     config.sorterFn = config.fn;
44943                 }
44944
44945                 
44946                 if (typeof config == 'function') {
44947                     config = {
44948                         sorterFn: config
44949                     };
44950                 }
44951
44952                 groupers[i] = new Grouper(config);
44953             }
44954         }
44955
44956         return groupers;
44957     },
44958
44959     
44960     group: function(groupers, direction) {
44961         var me = this,
44962             hasNew = false,
44963             grouper,
44964             newGroupers;
44965
44966         if (Ext.isArray(groupers)) {
44967             newGroupers = groupers;
44968         } else if (Ext.isObject(groupers)) {
44969             newGroupers = [groupers];
44970         } else if (Ext.isString(groupers)) {
44971             grouper = me.groupers.get(groupers);
44972
44973             if (!grouper) {
44974                 grouper = {
44975                     property : groupers,
44976                     direction: direction
44977                 };
44978                 newGroupers = [grouper];
44979             } else if (direction === undefined) {
44980                 grouper.toggle();
44981             } else {
44982                 grouper.setDirection(direction);
44983             }
44984         }
44985
44986         if (newGroupers && newGroupers.length) {
44987             hasNew = true;
44988             newGroupers = me.decodeGroupers(newGroupers);
44989             me.groupers.clear();
44990             me.groupers.addAll(newGroupers);
44991         }
44992
44993         if (me.remoteGroup) {
44994             me.load({
44995                 scope: me,
44996                 callback: me.fireGroupChange
44997             });
44998         } else {
44999             
45000             me.sort(null, null, null, hasNew);
45001             me.fireGroupChange();
45002         }
45003     },
45004
45005     
45006     clearGrouping: function(){
45007         var me = this;
45008         
45009         me.groupers.each(function(grouper){
45010             me.sorters.remove(grouper);
45011         });
45012         me.groupers.clear();
45013         if (me.remoteGroup) {
45014             me.load({
45015                 scope: me,
45016                 callback: me.fireGroupChange
45017             });
45018         } else {
45019             me.sort();
45020             me.fireEvent('groupchange', me, me.groupers);
45021         }
45022     },
45023
45024     
45025     isGrouped: function() {
45026         return this.groupers.getCount() > 0;
45027     },
45028
45029     
45030     fireGroupChange: function(){
45031         this.fireEvent('groupchange', this, this.groupers);
45032     },
45033
45034     
45035     getGroups: function(requestGroupString) {
45036         var records = this.data.items,
45037             length = records.length,
45038             groups = [],
45039             pointers = {},
45040             record,
45041             groupStr,
45042             group,
45043             i;
45044
45045         for (i = 0; i < length; i++) {
45046             record = records[i];
45047             groupStr = this.getGroupString(record);
45048             group = pointers[groupStr];
45049
45050             if (group === undefined) {
45051                 group = {
45052                     name: groupStr,
45053                     children: []
45054                 };
45055
45056                 groups.push(group);
45057                 pointers[groupStr] = group;
45058             }
45059
45060             group.children.push(record);
45061         }
45062
45063         return requestGroupString ? pointers[requestGroupString] : groups;
45064     },
45065
45066     
45067     getGroupsForGrouper: function(records, grouper) {
45068         var length = records.length,
45069             groups = [],
45070             oldValue,
45071             newValue,
45072             record,
45073             group,
45074             i;
45075
45076         for (i = 0; i < length; i++) {
45077             record = records[i];
45078             newValue = grouper.getGroupString(record);
45079
45080             if (newValue !== oldValue) {
45081                 group = {
45082                     name: newValue,
45083                     grouper: grouper,
45084                     records: []
45085                 };
45086                 groups.push(group);
45087             }
45088
45089             group.records.push(record);
45090
45091             oldValue = newValue;
45092         }
45093
45094         return groups;
45095     },
45096
45097     
45098     getGroupsForGrouperIndex: function(records, grouperIndex) {
45099         var me = this,
45100             groupers = me.groupers,
45101             grouper = groupers.getAt(grouperIndex),
45102             groups = me.getGroupsForGrouper(records, grouper),
45103             length = groups.length,
45104             i;
45105
45106         if (grouperIndex + 1 < groupers.length) {
45107             for (i = 0; i < length; i++) {
45108                 groups[i].children = me.getGroupsForGrouperIndex(groups[i].records, grouperIndex + 1);
45109             }
45110         }
45111
45112         for (i = 0; i < length; i++) {
45113             groups[i].depth = grouperIndex;
45114         }
45115
45116         return groups;
45117     },
45118
45119     
45120     getGroupData: function(sort) {
45121         var me = this;
45122         if (sort !== false) {
45123             me.sort();
45124         }
45125
45126         return me.getGroupsForGrouperIndex(me.data.items, 0);
45127     },
45128
45129     
45130     getGroupString: function(instance) {
45131         var group = this.groupers.first();
45132         if (group) {
45133             return instance.get(group.property);
45134         }
45135         return '';
45136     },
45137     
45138     insert: function(index, records) {
45139         var me = this,
45140             sync = false,
45141             i,
45142             record,
45143             len;
45144
45145         records = [].concat(records);
45146         for (i = 0, len = records.length; i < len; i++) {
45147             record = me.createModel(records[i]);
45148             record.set(me.modelDefaults);
45149             
45150             records[i] = record;
45151
45152             me.data.insert(index + i, record);
45153             record.join(me);
45154
45155             sync = sync || record.phantom === true;
45156         }
45157
45158         if (me.snapshot) {
45159             me.snapshot.addAll(records);
45160         }
45161
45162         me.fireEvent('add', me, records, index);
45163         me.fireEvent('datachanged', me);
45164         if (me.autoSync && sync) {
45165             me.sync();
45166         }
45167     },
45168
45169     
45170     add: function(records) {
45171         
45172         if (!Ext.isArray(records)) {
45173             records = Array.prototype.slice.apply(arguments);
45174         }
45175
45176         var me = this,
45177             i = 0,
45178             length = records.length,
45179             record;
45180
45181         for (; i < length; i++) {
45182             record = me.createModel(records[i]);
45183             
45184             records[i] = record;
45185         }
45186
45187         me.insert(me.data.length, records);
45188
45189         return records;
45190     },
45191
45192     
45193     createModel: function(record) {
45194         if (!record.isModel) {
45195             record = Ext.ModelManager.create(record, this.model);
45196         }
45197
45198         return record;
45199     },
45200
45201     
45202     each: function(fn, scope) {
45203         this.data.each(fn, scope);
45204     },
45205
45206     
45207     remove: function(records,  isMove) {
45208         if (!Ext.isArray(records)) {
45209             records = [records];
45210         }
45211
45212         
45213         isMove = isMove === true;
45214         var me = this,
45215             sync = false,
45216             i = 0,
45217             length = records.length,
45218             isPhantom,
45219             index,
45220             record;
45221
45222         for (; i < length; i++) {
45223             record = records[i];
45224             index = me.data.indexOf(record);
45225
45226             if (me.snapshot) {
45227                 me.snapshot.remove(record);
45228             }
45229
45230             if (index > -1) {
45231                 isPhantom = record.phantom === true;
45232                 if (!isMove && !isPhantom) {
45233                     
45234                     me.removed.push(record);
45235                 }
45236
45237                 record.unjoin(me);
45238                 me.data.remove(record);
45239                 sync = sync || !isPhantom;
45240
45241                 me.fireEvent('remove', me, record, index);
45242             }
45243         }
45244
45245         me.fireEvent('datachanged', me);
45246         if (!isMove && me.autoSync && sync) {
45247             me.sync();
45248         }
45249     },
45250
45251     
45252     removeAt: function(index) {
45253         var record = this.getAt(index);
45254
45255         if (record) {
45256             this.remove(record);
45257         }
45258     },
45259
45260     
45261     load: function(options) {
45262         var me = this;
45263
45264         options = options || {};
45265
45266         if (Ext.isFunction(options)) {
45267             options = {
45268                 callback: options
45269             };
45270         }
45271
45272         Ext.applyIf(options, {
45273             groupers: me.groupers.items,
45274             page: me.currentPage,
45275             start: (me.currentPage - 1) * me.pageSize,
45276             limit: me.pageSize,
45277             addRecords: false
45278         });
45279
45280         return me.callParent([options]);
45281     },
45282
45283     
45284     onProxyLoad: function(operation) {
45285         var me = this,
45286             resultSet = operation.getResultSet(),
45287             records = operation.getRecords(),
45288             successful = operation.wasSuccessful();
45289
45290         if (resultSet) {
45291             me.totalCount = resultSet.total;
45292         }
45293
45294         if (successful) {
45295             me.loadRecords(records, operation);
45296         }
45297
45298         me.loading = false;
45299         me.fireEvent('load', me, records, successful);
45300
45301         
45302         
45303         me.fireEvent('read', me, records, operation.wasSuccessful());
45304
45305         
45306         Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]);
45307     },
45308
45309     
45310     onCreateRecords: function(records, operation, success) {
45311         if (success) {
45312             var i = 0,
45313                 data = this.data,
45314                 snapshot = this.snapshot,
45315                 length = records.length,
45316                 originalRecords = operation.records,
45317                 record,
45318                 original,
45319                 index;
45320
45321             
45322             for (; i < length; ++i) {
45323                 record = records[i];
45324                 original = originalRecords[i];
45325                 if (original) {
45326                     index = data.indexOf(original);
45327                     if (index > -1) {
45328                         data.removeAt(index);
45329                         data.insert(index, record);
45330                     }
45331                     if (snapshot) {
45332                         index = snapshot.indexOf(original);
45333                         if (index > -1) {
45334                             snapshot.removeAt(index);
45335                             snapshot.insert(index, record);
45336                         }
45337                     }
45338                     record.phantom = false;
45339                     record.join(this);
45340                 }
45341             }
45342         }
45343     },
45344
45345     
45346     onUpdateRecords: function(records, operation, success){
45347         if (success) {
45348             var i = 0,
45349                 length = records.length,
45350                 data = this.data,
45351                 snapshot = this.snapshot,
45352                 record;
45353
45354             for (; i < length; ++i) {
45355                 record = records[i];
45356                 data.replace(record);
45357                 if (snapshot) {
45358                     snapshot.replace(record);
45359                 }
45360                 record.join(this);
45361             }
45362         }
45363     },
45364
45365     
45366     onDestroyRecords: function(records, operation, success){
45367         if (success) {
45368             var me = this,
45369                 i = 0,
45370                 length = records.length,
45371                 data = me.data,
45372                 snapshot = me.snapshot,
45373                 record;
45374
45375             for (; i < length; ++i) {
45376                 record = records[i];
45377                 record.unjoin(me);
45378                 data.remove(record);
45379                 if (snapshot) {
45380                     snapshot.remove(record);
45381                 }
45382             }
45383             me.removed = [];
45384         }
45385     },
45386
45387     
45388     getNewRecords: function() {
45389         return this.data.filterBy(this.filterNew).items;
45390     },
45391
45392     
45393     getUpdatedRecords: function() {
45394         return this.data.filterBy(this.filterUpdated).items;
45395     },
45396
45397     
45398     filter: function(filters, value) {
45399         if (Ext.isString(filters)) {
45400             filters = {
45401                 property: filters,
45402                 value: value
45403             };
45404         }
45405
45406         var me = this,
45407             decoded = me.decodeFilters(filters),
45408             i = 0,
45409             doLocalSort = me.sortOnFilter && !me.remoteSort,
45410             length = decoded.length;
45411
45412         for (; i < length; i++) {
45413             me.filters.replace(decoded[i]);
45414         }
45415
45416         if (me.remoteFilter) {
45417             
45418             me.load();
45419         } else {
45420             
45421             if (me.filters.getCount()) {
45422                 me.snapshot = me.snapshot || me.data.clone();
45423                 me.data = me.data.filter(me.filters.items);
45424
45425                 if (doLocalSort) {
45426                     me.sort();
45427                 }
45428                 
45429                 if (!doLocalSort || me.sorters.length < 1) {
45430                     me.fireEvent('datachanged', me);
45431                 }
45432             }
45433         }
45434     },
45435
45436     
45437     clearFilter: function(suppressEvent) {
45438         var me = this;
45439
45440         me.filters.clear();
45441
45442         if (me.remoteFilter) {
45443             me.load();
45444         } else if (me.isFiltered()) {
45445             me.data = me.snapshot.clone();
45446             delete me.snapshot;
45447
45448             if (suppressEvent !== true) {
45449                 me.fireEvent('datachanged', me);
45450             }
45451         }
45452     },
45453
45454     
45455     isFiltered: function() {
45456         var snapshot = this.snapshot;
45457         return !! snapshot && snapshot !== this.data;
45458     },
45459
45460     
45461     filterBy: function(fn, scope) {
45462         var me = this;
45463
45464         me.snapshot = me.snapshot || me.data.clone();
45465         me.data = me.queryBy(fn, scope || me);
45466         me.fireEvent('datachanged', me);
45467     },
45468
45469     
45470     queryBy: function(fn, scope) {
45471         var me = this,
45472         data = me.snapshot || me.data;
45473         return data.filterBy(fn, scope || me);
45474     },
45475
45476     
45477     loadData: function(data, append) {
45478         var model = this.model,
45479             length = data.length,
45480             newData = [],
45481             i,
45482             record;
45483
45484         
45485         for (i = 0; i < length; i++) {
45486             record = data[i];
45487
45488             if (!(record instanceof Ext.data.Model)) {
45489                 record = Ext.ModelManager.create(record, model);
45490             }
45491             newData.push(record);
45492         }
45493
45494         this.loadRecords(newData, {addRecords: append});
45495     },
45496
45497
45498     
45499     loadRawData : function(data, append) {
45500          var me      = this,
45501              result  = me.proxy.reader.read(data),
45502              records = result.records;
45503
45504          if (result.success) {
45505              me.loadRecords(records, { addRecords: append });
45506              me.fireEvent('load', me, records, true);
45507          }
45508      },
45509
45510
45511     
45512     loadRecords: function(records, options) {
45513         var me     = this,
45514             i      = 0,
45515             length = records.length;
45516
45517         options = options || {};
45518
45519
45520         if (!options.addRecords) {
45521             delete me.snapshot;
45522             me.clearData();
45523         }
45524
45525         me.data.addAll(records);
45526
45527         
45528         for (; i < length; i++) {
45529             if (options.start !== undefined) {
45530                 records[i].index = options.start + i;
45531
45532             }
45533             records[i].join(me);
45534         }
45535
45536         
45537         me.suspendEvents();
45538
45539         if (me.filterOnLoad && !me.remoteFilter) {
45540             me.filter();
45541         }
45542
45543         if (me.sortOnLoad && !me.remoteSort) {
45544             me.sort();
45545         }
45546
45547         me.resumeEvents();
45548         me.fireEvent('datachanged', me, records);
45549     },
45550
45551     
45552     
45553     loadPage: function(page, options) {
45554         var me = this;
45555         options = Ext.apply({}, options);
45556
45557         me.currentPage = page;
45558
45559         me.read(Ext.applyIf(options, {
45560             page: page,
45561             start: (page - 1) * me.pageSize,
45562             limit: me.pageSize,
45563             addRecords: !me.clearOnPageLoad
45564         }));
45565     },
45566
45567     
45568     nextPage: function(options) {
45569         this.loadPage(this.currentPage + 1, options);
45570     },
45571
45572     
45573     previousPage: function(options) {
45574         this.loadPage(this.currentPage - 1, options);
45575     },
45576
45577     
45578     clearData: function() {
45579         var me = this;
45580         me.data.each(function(record) {
45581             record.unjoin(me);
45582         });
45583
45584         me.data.clear();
45585     },
45586
45587     
45588     
45589     prefetch: function(options) {
45590         var me = this,
45591             operation,
45592             requestId = me.getRequestId();
45593
45594         options = options || {};
45595
45596         Ext.applyIf(options, {
45597             action : 'read',
45598             filters: me.filters.items,
45599             sorters: me.sorters.items,
45600             requestId: requestId
45601         });
45602         me.pendingRequests.push(requestId);
45603
45604         operation = Ext.create('Ext.data.Operation', options);
45605
45606         
45607         
45608         
45609         
45610         if (me.fireEvent('beforeprefetch', me, operation) !== false) {
45611             me.loading = true;
45612             me.proxy.read(operation, me.onProxyPrefetch, me);
45613         }
45614
45615         return me;
45616     },
45617
45618     
45619     prefetchPage: function(page, options) {
45620         var me = this,
45621             pageSize = me.pageSize,
45622             start = (page - 1) * me.pageSize,
45623             end = start + pageSize;
45624
45625         
45626         if (Ext.Array.indexOf(me.pagesRequested, page) === -1 && !me.rangeSatisfied(start, end)) {
45627             options = options || {};
45628             me.pagesRequested.push(page);
45629             Ext.applyIf(options, {
45630                 page : page,
45631                 start: start,
45632                 limit: pageSize,
45633                 callback: me.onWaitForGuarantee,
45634                 scope: me
45635             });
45636
45637             me.prefetch(options);
45638         }
45639
45640     },
45641
45642     
45643     getRequestId: function() {
45644         this.requestSeed = this.requestSeed || 1;
45645         return this.requestSeed++;
45646     },
45647
45648     
45649     onProxyPrefetch: function(operation) {
45650         var me         = this,
45651             resultSet  = operation.getResultSet(),
45652             records    = operation.getRecords(),
45653
45654             successful = operation.wasSuccessful();
45655
45656         if (resultSet) {
45657             me.totalCount = resultSet.total;
45658             me.fireEvent('totalcountchange', me.totalCount);
45659         }
45660
45661         if (successful) {
45662             me.cacheRecords(records, operation);
45663         }
45664         Ext.Array.remove(me.pendingRequests, operation.requestId);
45665         if (operation.page) {
45666             Ext.Array.remove(me.pagesRequested, operation.page);
45667         }
45668
45669         me.loading = false;
45670         me.fireEvent('prefetch', me, records, successful, operation);
45671
45672         
45673         if (operation.blocking) {
45674             me.fireEvent('load', me, records, successful);
45675         }
45676
45677         
45678         Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]);
45679     },
45680
45681     
45682     cacheRecords: function(records, operation) {
45683         var me     = this,
45684             i      = 0,
45685             length = records.length,
45686             start  = operation ? operation.start : 0;
45687
45688         if (!Ext.isDefined(me.totalCount)) {
45689             me.totalCount = records.length;
45690             me.fireEvent('totalcountchange', me.totalCount);
45691         }
45692
45693         for (; i < length; i++) {
45694             
45695             records[i].index = start + i;
45696         }
45697
45698         me.prefetchData.addAll(records);
45699         if (me.purgePageCount) {
45700             me.purgeRecords();
45701         }
45702
45703     },
45704
45705
45706     
45707     purgeRecords: function() {
45708         var me = this,
45709             prefetchCount = me.prefetchData.getCount(),
45710             purgeCount = me.purgePageCount * me.pageSize,
45711             numRecordsToPurge = prefetchCount - purgeCount - 1,
45712             i = 0;
45713
45714         for (; i <= numRecordsToPurge; i++) {
45715             me.prefetchData.removeAt(0);
45716         }
45717     },
45718
45719     
45720     rangeSatisfied: function(start, end) {
45721         var me = this,
45722             i = start,
45723             satisfied = true;
45724
45725         for (; i < end; i++) {
45726             if (!me.prefetchData.getByKey(i)) {
45727                 satisfied = false;
45728                 break;
45729             }
45730         }
45731         return satisfied;
45732     },
45733
45734     
45735     getPageFromRecordIndex: function(index) {
45736         return Math.floor(index / this.pageSize) + 1;
45737     },
45738
45739     
45740     onGuaranteedRange: function() {
45741         var me = this,
45742             totalCount = me.getTotalCount(),
45743             start = me.requestStart,
45744             end = ((totalCount - 1) < me.requestEnd) ? totalCount - 1 : me.requestEnd,
45745             range = [],
45746             record,
45747             i = start;
45748
45749         end = Math.max(0, end);
45750
45751
45752         if (start !== me.guaranteedStart && end !== me.guaranteedEnd) {
45753             me.guaranteedStart = start;
45754             me.guaranteedEnd = end;
45755
45756             for (; i <= end; i++) {
45757                 record = me.prefetchData.getByKey(i);
45758                 if (record) {
45759                     range.push(record);
45760                 }
45761             }
45762             me.fireEvent('guaranteedrange', range, start, end);
45763             if (me.cb) {
45764                 me.cb.call(me.scope || me, range);
45765             }
45766         }
45767
45768         me.unmask();
45769     },
45770
45771     
45772     mask: function() {
45773         this.masked = true;
45774         this.fireEvent('beforeload');
45775     },
45776
45777     
45778     unmask: function() {
45779         if (this.masked) {
45780             this.fireEvent('load');
45781         }
45782     },
45783
45784     
45785     hasPendingRequests: function() {
45786         return this.pendingRequests.length;
45787     },
45788
45789
45790     
45791     onWaitForGuarantee: function() {
45792         if (!this.hasPendingRequests()) {
45793             this.onGuaranteedRange();
45794         }
45795     },
45796
45797     
45798     guaranteeRange: function(start, end, cb, scope) {
45799
45800         end = (end > this.totalCount) ? this.totalCount - 1 : end;
45801
45802         var me = this,
45803             i = start,
45804             prefetchData = me.prefetchData,
45805             range = [],
45806             startLoaded = !!prefetchData.getByKey(start),
45807             endLoaded = !!prefetchData.getByKey(end),
45808             startPage = me.getPageFromRecordIndex(start),
45809             endPage = me.getPageFromRecordIndex(end);
45810
45811         me.cb = cb;
45812         me.scope = scope;
45813
45814         me.requestStart = start;
45815         me.requestEnd = end;
45816         
45817         if (!startLoaded || !endLoaded) {
45818             
45819             if (startPage === endPage) {
45820                 me.mask();
45821                 me.prefetchPage(startPage, {
45822                     
45823                     callback: me.onWaitForGuarantee,
45824                     scope: me
45825                 });
45826             
45827             } else {
45828                 me.mask();
45829                 me.prefetchPage(startPage, {
45830                     
45831                     callback: me.onWaitForGuarantee,
45832                     scope: me
45833                 });
45834                 me.prefetchPage(endPage, {
45835                     
45836                     callback: me.onWaitForGuarantee,
45837                     scope: me
45838                 });
45839             }
45840         
45841         } else {
45842             me.onGuaranteedRange();
45843         }
45844     },
45845
45846     
45847     
45848     sort: function() {
45849         var me = this,
45850             prefetchData = me.prefetchData,
45851             sorters,
45852             start,
45853             end,
45854             range;
45855
45856         if (me.buffered) {
45857             if (me.remoteSort) {
45858                 prefetchData.clear();
45859                 me.callParent(arguments);
45860             } else {
45861                 sorters = me.getSorters();
45862                 start = me.guaranteedStart;
45863                 end = me.guaranteedEnd;
45864
45865                 if (sorters.length) {
45866                     prefetchData.sort(sorters);
45867                     range = prefetchData.getRange();
45868                     prefetchData.clear();
45869                     me.cacheRecords(range);
45870                     delete me.guaranteedStart;
45871                     delete me.guaranteedEnd;
45872                     me.guaranteeRange(start, end);
45873                 }
45874                 me.callParent(arguments);
45875             }
45876         } else {
45877             me.callParent(arguments);
45878         }
45879     },
45880
45881     
45882     
45883     
45884     doSort: function(sorterFn) {
45885         var me = this;
45886         if (me.remoteSort) {
45887             
45888             me.load();
45889         } else {
45890             me.data.sortBy(sorterFn);
45891             if (!me.buffered) {
45892                 var range = me.getRange(),
45893                     ln = range.length,
45894                     i  = 0;
45895                 for (; i < ln; i++) {
45896                     range[i].index = i;
45897                 }
45898             }
45899             me.fireEvent('datachanged', me);
45900         }
45901     },
45902
45903     
45904     find: function(property, value, start, anyMatch, caseSensitive, exactMatch) {
45905         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive, exactMatch);
45906         return fn ? this.data.findIndexBy(fn, null, start) : -1;
45907     },
45908
45909     
45910     findRecord: function() {
45911         var me = this,
45912             index = me.find.apply(me, arguments);
45913         return index !== -1 ? me.getAt(index) : null;
45914     },
45915
45916     
45917     createFilterFn: function(property, value, anyMatch, caseSensitive, exactMatch) {
45918         if (Ext.isEmpty(value)) {
45919             return false;
45920         }
45921         value = this.data.createValueMatcher(value, anyMatch, caseSensitive, exactMatch);
45922         return function(r) {
45923             return value.test(r.data[property]);
45924         };
45925     },
45926
45927     
45928     findExact: function(property, value, start) {
45929         return this.data.findIndexBy(function(rec) {
45930             return rec.get(property) == value;
45931         },
45932         this, start);
45933     },
45934
45935     
45936     findBy: function(fn, scope, start) {
45937         return this.data.findIndexBy(fn, scope, start);
45938     },
45939
45940     
45941     collect: function(dataIndex, allowNull, bypassFilter) {
45942         var me = this,
45943             data = (bypassFilter === true && me.snapshot) ? me.snapshot: me.data;
45944
45945         return data.collect(dataIndex, 'data', allowNull);
45946     },
45947
45948     
45949     getCount: function() {
45950         return this.data.length || 0;
45951     },
45952
45953     
45954     getTotalCount: function() {
45955         return this.totalCount;
45956     },
45957
45958     
45959     getAt: function(index) {
45960         return this.data.getAt(index);
45961     },
45962
45963     
45964     getRange: function(start, end) {
45965         return this.data.getRange(start, end);
45966     },
45967
45968     
45969     getById: function(id) {
45970         return (this.snapshot || this.data).findBy(function(record) {
45971             return record.getId() === id;
45972         });
45973     },
45974
45975     
45976     indexOf: function(record) {
45977         return this.data.indexOf(record);
45978     },
45979
45980
45981     
45982     indexOfTotal: function(record) {
45983         var index = record.index;
45984         if (index || index === 0) {
45985             return index;
45986         }
45987         return this.indexOf(record);
45988     },
45989
45990     
45991     indexOfId: function(id) {
45992         return this.indexOf(this.getById(id));
45993     },
45994
45995     
45996     removeAll: function(silent) {
45997         var me = this;
45998
45999         me.clearData();
46000         if (me.snapshot) {
46001             me.snapshot.clear();
46002         }
46003         if (silent !== true) {
46004             me.fireEvent('clear', me);
46005         }
46006     },
46007
46008     
46009
46010     
46011     first: function(grouped) {
46012         var me = this;
46013
46014         if (grouped && me.isGrouped()) {
46015             return me.aggregate(function(records) {
46016                 return records.length ? records[0] : undefined;
46017             }, me, true);
46018         } else {
46019             return me.data.first();
46020         }
46021     },
46022
46023     
46024     last: function(grouped) {
46025         var me = this;
46026
46027         if (grouped && me.isGrouped()) {
46028             return me.aggregate(function(records) {
46029                 var len = records.length;
46030                 return len ? records[len - 1] : undefined;
46031             }, me, true);
46032         } else {
46033             return me.data.last();
46034         }
46035     },
46036
46037     
46038     sum: function(field, grouped) {
46039         var me = this;
46040
46041         if (grouped && me.isGrouped()) {
46042             return me.aggregate(me.getSum, me, true, [field]);
46043         } else {
46044             return me.getSum(me.data.items, field);
46045         }
46046     },
46047
46048     
46049     getSum: function(records, field) {
46050         var total = 0,
46051             i = 0,
46052             len = records.length;
46053
46054         for (; i < len; ++i) {
46055             total += records[i].get(field);
46056         }
46057
46058         return total;
46059     },
46060
46061     
46062     count: function(grouped) {
46063         var me = this;
46064
46065         if (grouped && me.isGrouped()) {
46066             return me.aggregate(function(records) {
46067                 return records.length;
46068             }, me, true);
46069         } else {
46070             return me.getCount();
46071         }
46072     },
46073
46074     
46075     min: function(field, grouped) {
46076         var me = this;
46077
46078         if (grouped && me.isGrouped()) {
46079             return me.aggregate(me.getMin, me, true, [field]);
46080         } else {
46081             return me.getMin(me.data.items, field);
46082         }
46083     },
46084
46085     
46086     getMin: function(records, field){
46087         var i = 1,
46088             len = records.length,
46089             value, min;
46090
46091         if (len > 0) {
46092             min = records[0].get(field);
46093         }
46094
46095         for (; i < len; ++i) {
46096             value = records[i].get(field);
46097             if (value < min) {
46098                 min = value;
46099             }
46100         }
46101         return min;
46102     },
46103
46104     
46105     max: function(field, grouped) {
46106         var me = this;
46107
46108         if (grouped && me.isGrouped()) {
46109             return me.aggregate(me.getMax, me, true, [field]);
46110         } else {
46111             return me.getMax(me.data.items, field);
46112         }
46113     },
46114
46115     
46116     getMax: function(records, field) {
46117         var i = 1,
46118             len = records.length,
46119             value,
46120             max;
46121
46122         if (len > 0) {
46123             max = records[0].get(field);
46124         }
46125
46126         for (; i < len; ++i) {
46127             value = records[i].get(field);
46128             if (value > max) {
46129                 max = value;
46130             }
46131         }
46132         return max;
46133     },
46134
46135     
46136     average: function(field, grouped) {
46137         var me = this;
46138         if (grouped && me.isGrouped()) {
46139             return me.aggregate(me.getAverage, me, true, [field]);
46140         } else {
46141             return me.getAverage(me.data.items, field);
46142         }
46143     },
46144
46145     
46146     getAverage: function(records, field) {
46147         var i = 0,
46148             len = records.length,
46149             sum = 0;
46150
46151         if (records.length > 0) {
46152             for (; i < len; ++i) {
46153                 sum += records[i].get(field);
46154             }
46155             return sum / len;
46156         }
46157         return 0;
46158     },
46159
46160     
46161     aggregate: function(fn, scope, grouped, args) {
46162         args = args || [];
46163         if (grouped && this.isGrouped()) {
46164             var groups = this.getGroups(),
46165                 i = 0,
46166                 len = groups.length,
46167                 out = {},
46168                 group;
46169
46170             for (; i < len; ++i) {
46171                 group = groups[i];
46172                 out[group.name] = fn.apply(scope || this, [group.children].concat(args));
46173             }
46174             return out;
46175         } else {
46176             return fn.apply(scope || this, [this.data.items].concat(args));
46177         }
46178     }
46179 }, function() {
46180     
46181     
46182     
46183     Ext.regStore('ext-empty-store', {fields: [], proxy: 'proxy'});
46184 });
46185
46186
46187 Ext.define('Ext.data.JsonStore',  {
46188     extend: 'Ext.data.Store',
46189     alias: 'store.json',
46190
46191     
46192     constructor: function(config) {
46193         config = config || {};
46194
46195         Ext.applyIf(config, {
46196             proxy: {
46197                 type  : 'ajax',
46198                 reader: 'json',
46199                 writer: 'json'
46200             }
46201         });
46202
46203         this.callParent([config]);
46204     }
46205 });
46206
46207
46208 Ext.define('Ext.chart.axis.Time', {
46209
46210     
46211
46212     extend: 'Ext.chart.axis.Numeric',
46213
46214     alternateClassName: 'Ext.chart.TimeAxis',
46215
46216     alias: 'axis.time',
46217
46218     requires: ['Ext.data.Store', 'Ext.data.JsonStore'],
46219
46220     
46221
46222     
46223     dateFormat: false,
46224
46225     
46226     fromDate: false,
46227
46228     
46229     toDate: false,
46230
46231     
46232     step: [Ext.Date.DAY, 1],
46233     
46234     
46235     constrain: false,
46236
46237     
46238     roundToDecimal: false,
46239     
46240     constructor: function (config) {
46241         var me = this, label, f, df;
46242         me.callParent([config]);
46243         label = me.label || {};
46244         df = this.dateFormat;
46245         if (df) {
46246             if (label.renderer) {
46247                 f = label.renderer;
46248                 label.renderer = function(v) {
46249                     v = f(v);
46250                     return Ext.Date.format(new Date(f(v)), df);
46251                 };
46252             } else {
46253                 label.renderer = function(v) {
46254                     return Ext.Date.format(new Date(v >> 0), df);
46255                 };
46256             }
46257         }
46258     },
46259
46260     doConstrain: function () {
46261         var me = this,
46262             store = me.chart.store,
46263             data = [],
46264             series = me.chart.series.items,
46265             math = Math,
46266             mmax = math.max,
46267             mmin = math.min,
46268             fields = me.fields,
46269             ln = fields.length,
46270             range = me.getRange(),
46271             min = range.min, max = range.max, i, l, excludes = [],
46272             value, values, rec, data = [];
46273         for (i = 0, l = series.length; i < l; i++) {
46274             excludes[i] = series[i].__excludes;
46275         }
46276         store.each(function(record) {
46277             for (i = 0; i < ln; i++) {
46278                 if (excludes[i]) {
46279                     continue;
46280                 }
46281                 value = record.get(fields[i]);
46282                 if (+value < +min) return;
46283                 if (+value > +max) return;
46284             }
46285             data.push(record);
46286         })
46287         me.chart.substore = Ext.create('Ext.data.JsonStore', { model: store.model, data: data });
46288     },
46289
46290     
46291     processView: function () {
46292         var me = this;
46293         if (me.fromDate) {
46294             me.minimum = +me.fromDate;
46295         }
46296         if (me.toDate) {
46297             me.maximum = +me.toDate;
46298         }
46299         if (me.constrain) {
46300             me.doConstrain();
46301         }
46302      },
46303
46304     
46305     calcEnds: function() {
46306         var me = this, range, step = me.step;
46307         if (step) {
46308             range = me.getRange();
46309             range = Ext.draw.Draw.snapEndsByDateAndStep(new Date(range.min), new Date(range.max), Ext.isNumber(step) ? [Date.MILLI, step]: step);
46310             if (me.minimum) {
46311                 range.from = me.minimum;
46312             }
46313             if (me.maximum) {
46314                 range.to = me.maximum;
46315             }
46316             range.step = (range.to - range.from) / range.steps;
46317             return range;
46318         } else {
46319             return me.callParent(arguments);
46320         }
46321     }
46322  });
46323
46324
46325
46326 Ext.define('Ext.chart.series.Series', {
46327
46328     
46329
46330     mixins: {
46331         observable: 'Ext.util.Observable',
46332         labels: 'Ext.chart.Label',
46333         highlights: 'Ext.chart.Highlight',
46334         tips: 'Ext.chart.Tip',
46335         callouts: 'Ext.chart.Callout'
46336     },
46337
46338     
46339
46340     
46341
46342     
46343
46344     
46345     type: null,
46346
46347     
46348     title: null,
46349
46350     
46351     showInLegend: true,
46352
46353     
46354     renderer: function(sprite, record, attributes, index, store) {
46355         return attributes;
46356     },
46357
46358     
46359     shadowAttributes: null,
46360
46361     //@private triggerdrawlistener flag
46362
46363     triggerAfterDraw: false,
46364
46365     
46366
46367     constructor: function(config) {
46368         var me = this;
46369         if (config) {
46370             Ext.apply(me, config);
46371         }
46372
46373         me.shadowGroups = [];
46374
46375         me.mixins.labels.constructor.call(me, config);
46376         me.mixins.highlights.constructor.call(me, config);
46377         me.mixins.tips.constructor.call(me, config);
46378         me.mixins.callouts.constructor.call(me, config);
46379
46380         me.addEvents({
46381             scope: me,
46382             itemmouseover: true,
46383             itemmouseout: true,
46384             itemmousedown: true,
46385             itemmouseup: true,
46386             mouseleave: true,
46387             afterdraw: true,
46388
46389             
46390             titlechange: true
46391         });
46392
46393         me.mixins.observable.constructor.call(me, config);
46394
46395         me.on({
46396             scope: me,
46397             itemmouseover: me.onItemMouseOver,
46398             itemmouseout: me.onItemMouseOut,
46399             mouseleave: me.onMouseLeave
46400         });
46401     },
46402     
46403     
46404     eachRecord: function(fn, scope) {
46405         var chart = this.chart;
46406         (chart.substore || chart.store).each(fn, scope);
46407     },
46408
46409     
46410     getRecordCount: function() {
46411         var chart = this.chart,
46412             store = chart.substore || chart.store;
46413         return store ? store.getCount() : 0;
46414     },
46415
46416     
46417     isExcluded: function(index) {
46418         var excludes = this.__excludes;
46419         return !!(excludes && excludes[index]);
46420     },
46421
46422     
46423     setBBox: function(noGutter) {
46424         var me = this,
46425             chart = me.chart,
46426             chartBBox = chart.chartBBox,
46427             gutterX = noGutter ? 0 : chart.maxGutter[0],
46428             gutterY = noGutter ? 0 : chart.maxGutter[1],
46429             clipBox, bbox;
46430
46431         clipBox = {
46432             x: chartBBox.x,
46433             y: chartBBox.y,
46434             width: chartBBox.width,
46435             height: chartBBox.height
46436         };
46437         me.clipBox = clipBox;
46438
46439         bbox = {
46440             x: (clipBox.x + gutterX) - (chart.zoom.x * chart.zoom.width),
46441             y: (clipBox.y + gutterY) - (chart.zoom.y * chart.zoom.height),
46442             width: (clipBox.width - (gutterX * 2)) * chart.zoom.width,
46443             height: (clipBox.height - (gutterY * 2)) * chart.zoom.height
46444         };
46445         me.bbox = bbox;
46446     },
46447
46448     
46449     onAnimate: function(sprite, attr) {
46450         var me = this;
46451         sprite.stopAnimation();
46452         if (me.triggerAfterDraw) {
46453             return sprite.animate(Ext.applyIf(attr, me.chart.animate));
46454         } else {
46455             me.triggerAfterDraw = true;
46456             return sprite.animate(Ext.apply(Ext.applyIf(attr, me.chart.animate), {
46457                 listeners: {
46458                     'afteranimate': function() {
46459                         me.triggerAfterDraw = false;
46460                         me.fireEvent('afterrender');
46461                     }
46462                 }
46463             }));
46464         }
46465     },
46466
46467     
46468     getGutters: function() {
46469         return [0, 0];
46470     },
46471
46472     
46473     onItemMouseOver: function(item) {
46474         var me = this;
46475         if (item.series === me) {
46476             if (me.highlight) {
46477                 me.highlightItem(item);
46478             }
46479             if (me.tooltip) {
46480                 me.showTip(item);
46481             }
46482         }
46483     },
46484
46485     
46486     onItemMouseOut: function(item) {
46487         var me = this;
46488         if (item.series === me) {
46489             me.unHighlightItem();
46490             if (me.tooltip) {
46491                 me.hideTip(item);
46492             }
46493         }
46494     },
46495
46496     
46497     onMouseLeave: function() {
46498         var me = this;
46499         me.unHighlightItem();
46500         if (me.tooltip) {
46501             me.hideTip();
46502         }
46503     },
46504
46505     
46506     getItemForPoint: function(x, y) {
46507         
46508         if (!this.items || !this.items.length || this.seriesIsHidden) {
46509             return null;
46510         }
46511         var me = this,
46512             items = me.items,
46513             bbox = me.bbox,
46514             item, i, ln;
46515         
46516         if (!Ext.draw.Draw.withinBox(x, y, bbox)) {
46517             return null;
46518         }
46519         for (i = 0, ln = items.length; i < ln; i++) {
46520             if (items[i] && this.isItemInPoint(x, y, items[i], i)) {
46521                 return items[i];
46522             }
46523         }
46524
46525         return null;
46526     },
46527
46528     isItemInPoint: function(x, y, item, i) {
46529         return false;
46530     },
46531
46532     
46533     hideAll: function() {
46534         var me = this,
46535             items = me.items,
46536             item, len, i, j, l, sprite, shadows;
46537
46538         me.seriesIsHidden = true;
46539         me._prevShowMarkers = me.showMarkers;
46540
46541         me.showMarkers = false;
46542         
46543         me.hideLabels(0);
46544         
46545         for (i = 0, len = items.length; i < len; i++) {
46546             item = items[i];
46547             sprite = item.sprite;
46548             if (sprite) {
46549                 sprite.setAttributes({
46550                     hidden: true
46551                 }, true);
46552             }
46553
46554             if (sprite && sprite.shadows) {
46555                 shadows = sprite.shadows;
46556                 for (j = 0, l = shadows.length; j < l; ++j) {
46557                     shadows[j].setAttributes({
46558                         hidden: true
46559                     }, true);
46560                 }
46561             }
46562         }
46563     },
46564
46565     
46566     showAll: function() {
46567         var me = this,
46568             prevAnimate = me.chart.animate;
46569         me.chart.animate = false;
46570         me.seriesIsHidden = false;
46571         me.showMarkers = me._prevShowMarkers;
46572         me.drawSeries();
46573         me.chart.animate = prevAnimate;
46574     },
46575
46576     
46577     getLegendColor: function(index) {
46578         var me = this, fill, stroke;
46579         if (me.seriesStyle) {
46580             fill = me.seriesStyle.fill;
46581             stroke = me.seriesStyle.stroke;
46582             if (fill && fill != 'none') {
46583                 return fill;
46584             }
46585             return stroke;
46586         }
46587         return '#000';
46588     },
46589
46590     
46591     visibleInLegend: function(index){
46592         var excludes = this.__excludes;
46593         if (excludes) {
46594             return !excludes[index];
46595         }
46596         return !this.seriesIsHidden;
46597     },
46598
46599     
46600     setTitle: function(index, title) {
46601         var me = this,
46602             oldTitle = me.title;
46603
46604         if (Ext.isString(index)) {
46605             title = index;
46606             index = 0;
46607         }
46608
46609         if (Ext.isArray(oldTitle)) {
46610             oldTitle[index] = title;
46611         } else {
46612             me.title = title;
46613         }
46614
46615         me.fireEvent('titlechange', title, index);
46616     }
46617 });
46618
46619
46620 Ext.define('Ext.chart.series.Cartesian', {
46621
46622     
46623
46624     extend: 'Ext.chart.series.Series',
46625
46626     alternateClassName: ['Ext.chart.CartesianSeries', 'Ext.chart.CartesianChart'],
46627
46628     
46629
46630     
46631     xField: null,
46632
46633     
46634     yField: null,
46635
46636     
46637     axis: 'left',
46638
46639     getLegendLabels: function() {
46640         var me = this,
46641             labels = [],
46642             combinations = me.combinations;
46643
46644         Ext.each([].concat(me.yField), function(yField, i) {
46645             var title = me.title;
46646             
46647             labels.push((Ext.isArray(title) ? title[i] : title) || yField);
46648         });
46649
46650         
46651         if (combinations) {
46652             Ext.each(combinations, function(combo) {
46653                 var label0 = labels[combo[0]],
46654                     label1 = labels[combo[1]];
46655                 labels[combo[1]] = label0 + ' & ' + label1;
46656                 labels.splice(combo[0], 1);
46657             });
46658         }
46659
46660         return labels;
46661     },
46662
46663     
46664     eachYValue: function(record, fn, scope) {
46665         Ext.each(this.getYValueAccessors(), function(accessor, i) {
46666             fn.call(scope, accessor(record), i);
46667         });
46668     },
46669
46670     
46671     getYValueCount: function() {
46672         return this.getYValueAccessors().length;
46673     },
46674
46675     combine: function(index1, index2) {
46676         var me = this,
46677             accessors = me.getYValueAccessors(),
46678             accessor1 = accessors[index1],
46679             accessor2 = accessors[index2];
46680
46681         
46682         accessors[index2] = function(record) {
46683             return accessor1(record) + accessor2(record);
46684         };
46685         accessors.splice(index1, 1);
46686
46687         me.callParent([index1, index2]);
46688     },
46689
46690     clearCombinations: function() {
46691         
46692         delete this.yValueAccessors;
46693         this.callParent();
46694     },
46695
46696     
46697     getYValueAccessors: function() {
46698         var me = this,
46699             accessors = me.yValueAccessors;
46700         if (!accessors) {
46701             accessors = me.yValueAccessors = [];
46702             Ext.each([].concat(me.yField), function(yField) {
46703                 accessors.push(function(record) {
46704                     return record.get(yField);
46705                 });
46706             });
46707         }
46708         return accessors;
46709     },
46710
46711     
46712     getMinMaxXValues: function() {
46713         var me = this,
46714             min, max,
46715             xField = me.xField;
46716
46717         if (me.getRecordCount() > 0) {
46718             min = Infinity;
46719             max = -min;
46720             me.eachRecord(function(record) {
46721                 var xValue = record.get(xField);
46722                 if (xValue > max) {
46723                     max = xValue;
46724                 }
46725                 if (xValue < min) {
46726                     min = xValue;
46727                 }
46728             });
46729         } else {
46730             min = max = 0;
46731         }
46732         return [min, max];
46733     },
46734
46735     
46736     getMinMaxYValues: function() {
46737         var me = this,
46738             stacked = me.stacked,
46739             min, max,
46740             positiveTotal, negativeTotal;
46741
46742         function eachYValueStacked(yValue, i) {
46743             if (!me.isExcluded(i)) {
46744                 if (yValue < 0) {
46745                     negativeTotal += yValue;
46746                 } else {
46747                     positiveTotal += yValue;
46748                 }
46749             }
46750         }
46751
46752         function eachYValue(yValue, i) {
46753             if (!me.isExcluded(i)) {
46754                 if (yValue > max) {
46755                     max = yValue;
46756                 }
46757                 if (yValue < min) {
46758                     min = yValue;
46759                 }
46760             }
46761         }
46762
46763         if (me.getRecordCount() > 0) {
46764             min = Infinity;
46765             max = -min;
46766             me.eachRecord(function(record) {
46767                 if (stacked) {
46768                     positiveTotal = 0;
46769                     negativeTotal = 0;
46770                     me.eachYValue(record, eachYValueStacked);
46771                     if (positiveTotal > max) {
46772                         max = positiveTotal;
46773                     }
46774                     if (negativeTotal < min) {
46775                         min = negativeTotal;
46776                     }
46777                 } else {
46778                     me.eachYValue(record, eachYValue);
46779                 }
46780             });
46781         } else {
46782             min = max = 0;
46783         }
46784         return [min, max];
46785     },
46786
46787     getAxesForXAndYFields: function() {
46788         var me = this,
46789             axes = me.chart.axes,
46790             axis = [].concat(me.axis),
46791             xAxis, yAxis;
46792
46793         if (Ext.Array.indexOf(axis, 'top') > -1) {
46794             xAxis = 'top';
46795         } else if (Ext.Array.indexOf(axis, 'bottom') > -1) {
46796             xAxis = 'bottom';
46797         } else {
46798             if (axes.get('top')) {
46799                 xAxis = 'top';
46800             } else if (axes.get('bottom')) {
46801                 xAxis = 'bottom';
46802             }
46803         }
46804
46805         if (Ext.Array.indexOf(axis, 'left') > -1) {
46806             yAxis = 'left';
46807         } else if (Ext.Array.indexOf(axis, 'right') > -1) {
46808             yAxis = 'right';
46809         } else {
46810             if (axes.get('left')) {
46811                 yAxis = 'left';
46812             } else if (axes.get('right')) {
46813                 yAxis = 'right';
46814             }
46815         }
46816
46817         return {
46818             xAxis: xAxis,
46819             yAxis: yAxis
46820         };
46821     }
46822
46823
46824 });
46825
46826
46827 Ext.define('Ext.chart.series.Area', {
46828
46829     
46830
46831     extend: 'Ext.chart.series.Cartesian',
46832
46833     alias: 'series.area',
46834
46835     requires: ['Ext.chart.axis.Axis', 'Ext.draw.Color', 'Ext.fx.Anim'],
46836
46837     
46838
46839     type: 'area',
46840
46841     
46842     stacked: true,
46843
46844     
46845     style: {},
46846
46847     constructor: function(config) {
46848         this.callParent(arguments);
46849         var me = this,
46850             surface = me.chart.surface,
46851             i, l;
46852         Ext.apply(me, config, {
46853             __excludes: [],
46854             highlightCfg: {
46855                 lineWidth: 3,
46856                 stroke: '#55c',
46857                 opacity: 0.8,
46858                 color: '#f00'
46859             }
46860         });
46861         if (me.highlight) {
46862             me.highlightSprite = surface.add({
46863                 type: 'path',
46864                 path: ['M', 0, 0],
46865                 zIndex: 1000,
46866                 opacity: 0.3,
46867                 lineWidth: 5,
46868                 hidden: true,
46869                 stroke: '#444'
46870             });
46871         }
46872         me.group = surface.getGroup(me.seriesId);
46873     },
46874
46875     
46876     shrink: function(xValues, yValues, size) {
46877         var len = xValues.length,
46878             ratio = Math.floor(len / size),
46879             i, j,
46880             xSum = 0,
46881             yCompLen = this.areas.length,
46882             ySum = [],
46883             xRes = [],
46884             yRes = [];
46885         
46886         for (j = 0; j < yCompLen; ++j) {
46887             ySum[j] = 0;
46888         }
46889         for (i = 0; i < len; ++i) {
46890             xSum += xValues[i];
46891             for (j = 0; j < yCompLen; ++j) {
46892                 ySum[j] += yValues[i][j];
46893             }
46894             if (i % ratio == 0) {
46895                 
46896                 xRes.push(xSum/ratio);
46897                 for (j = 0; j < yCompLen; ++j) {
46898                     ySum[j] /= ratio;
46899                 }
46900                 yRes.push(ySum);
46901                 
46902                 xSum = 0;
46903                 for (j = 0, ySum = []; j < yCompLen; ++j) {
46904                     ySum[j] = 0;
46905                 }
46906             }
46907         }
46908         return {
46909             x: xRes,
46910             y: yRes
46911         };
46912     },
46913
46914     
46915     getBounds: function() {
46916         var me = this,
46917             chart = me.chart,
46918             store = chart.getChartStore(),
46919             areas = [].concat(me.yField),
46920             areasLen = areas.length,
46921             xValues = [],
46922             yValues = [],
46923             infinity = Infinity,
46924             minX = infinity,
46925             minY = infinity,
46926             maxX = -infinity,
46927             maxY = -infinity,
46928             math = Math,
46929             mmin = math.min,
46930             mmax = math.max,
46931             bbox, xScale, yScale, xValue, yValue, areaIndex, acumY, ln, sumValues, clipBox, areaElem;
46932
46933         me.setBBox();
46934         bbox = me.bbox;
46935
46936         
46937         if (me.axis) {
46938             axis = chart.axes.get(me.axis);
46939             if (axis) {
46940                 out = axis.calcEnds();
46941                 minY = out.from || axis.prevMin;
46942                 maxY = mmax(out.to || axis.prevMax, 0);
46943             }
46944         }
46945
46946         if (me.yField && !Ext.isNumber(minY)) {
46947             axis = Ext.create('Ext.chart.axis.Axis', {
46948                 chart: chart,
46949                 fields: [].concat(me.yField)
46950             });
46951             out = axis.calcEnds();
46952             minY = out.from || axis.prevMin;
46953             maxY = mmax(out.to || axis.prevMax, 0);
46954         }
46955
46956         if (!Ext.isNumber(minY)) {
46957             minY = 0;
46958         }
46959         if (!Ext.isNumber(maxY)) {
46960             maxY = 0;
46961         }
46962
46963         store.each(function(record, i) {
46964             xValue = record.get(me.xField);
46965             yValue = [];
46966             if (typeof xValue != 'number') {
46967                 xValue = i;
46968             }
46969             xValues.push(xValue);
46970             acumY = 0;
46971             for (areaIndex = 0; areaIndex < areasLen; areaIndex++) {
46972                 areaElem = record.get(areas[areaIndex]);
46973                 if (typeof areaElem == 'number') {
46974                     minY = mmin(minY, areaElem);
46975                     yValue.push(areaElem);
46976                     acumY += areaElem;
46977                 }
46978             }
46979             minX = mmin(minX, xValue);
46980             maxX = mmax(maxX, xValue);
46981             maxY = mmax(maxY, acumY);
46982             yValues.push(yValue);
46983         }, me);
46984
46985         xScale = bbox.width / ((maxX - minX) || 1);
46986         yScale = bbox.height / ((maxY - minY) || 1);
46987
46988         ln = xValues.length;
46989         if ((ln > bbox.width) && me.areas) {
46990             sumValues = me.shrink(xValues, yValues, bbox.width);
46991             xValues = sumValues.x;
46992             yValues = sumValues.y;
46993         }
46994
46995         return {
46996             bbox: bbox,
46997             minX: minX,
46998             minY: minY,
46999             xValues: xValues,
47000             yValues: yValues,
47001             xScale: xScale,
47002             yScale: yScale,
47003             areasLen: areasLen
47004         };
47005     },
47006
47007     
47008     getPaths: function() {
47009         var me = this,
47010             chart = me.chart,
47011             store = chart.getChartStore(),
47012             first = true,
47013             bounds = me.getBounds(),
47014             bbox = bounds.bbox,
47015             items = me.items = [],
47016             componentPaths = [],
47017             componentPath,
47018             paths = [],
47019             i, ln, x, y, xValue, yValue, acumY, areaIndex, prevAreaIndex, areaElem, path;
47020
47021         ln = bounds.xValues.length;
47022         
47023         for (i = 0; i < ln; i++) {
47024             xValue = bounds.xValues[i];
47025             yValue = bounds.yValues[i];
47026             x = bbox.x + (xValue - bounds.minX) * bounds.xScale;
47027             acumY = 0;
47028             for (areaIndex = 0; areaIndex < bounds.areasLen; areaIndex++) {
47029                 
47030                 if (me.__excludes[areaIndex]) {
47031                     continue;
47032                 }
47033                 if (!componentPaths[areaIndex]) {
47034                     componentPaths[areaIndex] = [];
47035                 }
47036                 areaElem = yValue[areaIndex];
47037                 acumY += areaElem;
47038                 y = bbox.y + bbox.height - (acumY - bounds.minY) * bounds.yScale;
47039                 if (!paths[areaIndex]) {
47040                     paths[areaIndex] = ['M', x, y];
47041                     componentPaths[areaIndex].push(['L', x, y]);
47042                 } else {
47043                     paths[areaIndex].push('L', x, y);
47044                     componentPaths[areaIndex].push(['L', x, y]);
47045                 }
47046                 if (!items[areaIndex]) {
47047                     items[areaIndex] = {
47048                         pointsUp: [],
47049                         pointsDown: [],
47050                         series: me
47051                     };
47052                 }
47053                 items[areaIndex].pointsUp.push([x, y]);
47054             }
47055         }
47056
47057         
47058         for (areaIndex = 0; areaIndex < bounds.areasLen; areaIndex++) {
47059             
47060             if (me.__excludes[areaIndex]) {
47061                 continue;
47062             }
47063             path = paths[areaIndex];
47064             
47065             if (areaIndex == 0 || first) {
47066                 first = false;
47067                 path.push('L', x, bbox.y + bbox.height,
47068                           'L', bbox.x, bbox.y + bbox.height,
47069                           'Z');
47070             }
47071             
47072             else {
47073                 componentPath = componentPaths[prevAreaIndex];
47074                 componentPath.reverse();
47075                 path.push('L', x, componentPath[0][2]);
47076                 for (i = 0; i < ln; i++) {
47077                     path.push(componentPath[i][0],
47078                               componentPath[i][1],
47079                               componentPath[i][2]);
47080                     items[areaIndex].pointsDown[ln -i -1] = [componentPath[i][1], componentPath[i][2]];
47081                 }
47082                 path.push('L', bbox.x, path[2], 'Z');
47083             }
47084             prevAreaIndex = areaIndex;
47085         }
47086         return {
47087             paths: paths,
47088             areasLen: bounds.areasLen
47089         };
47090     },
47091
47092     
47093     drawSeries: function() {
47094         var me = this,
47095             chart = me.chart,
47096             store = chart.getChartStore(),
47097             surface = chart.surface,
47098             animate = chart.animate,
47099             group = me.group,
47100             endLineStyle = Ext.apply(me.seriesStyle, me.style),
47101             colorArrayStyle = me.colorArrayStyle,
47102             colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
47103             areaIndex, areaElem, paths, path, rendererAttributes;
47104
47105         me.unHighlightItem();
47106         me.cleanHighlights();
47107
47108         if (!store || !store.getCount()) {
47109             return;
47110         }
47111
47112         paths = me.getPaths();
47113
47114         if (!me.areas) {
47115             me.areas = [];
47116         }
47117
47118         for (areaIndex = 0; areaIndex < paths.areasLen; areaIndex++) {
47119             
47120             if (me.__excludes[areaIndex]) {
47121                 continue;
47122             }
47123             if (!me.areas[areaIndex]) {
47124                 me.items[areaIndex].sprite = me.areas[areaIndex] = surface.add(Ext.apply({}, {
47125                     type: 'path',
47126                     group: group,
47127                     
47128                     path: paths.paths[areaIndex],
47129                     stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength],
47130                     fill: colorArrayStyle[areaIndex % colorArrayLength]
47131                 }, endLineStyle || {}));
47132             }
47133             areaElem = me.areas[areaIndex];
47134             path = paths.paths[areaIndex];
47135             if (animate) {
47136                 
47137                 rendererAttributes = me.renderer(areaElem, false, {
47138                     path: path,
47139                     
47140                     fill: colorArrayStyle[areaIndex % colorArrayLength],
47141                     stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength]
47142                 }, areaIndex, store);
47143                 
47144                 me.animation = me.onAnimate(areaElem, {
47145                     to: rendererAttributes
47146                 });
47147             } else {
47148                 rendererAttributes = me.renderer(areaElem, false, {
47149                     path: path,
47150                     
47151                     hidden: false,
47152                     fill: colorArrayStyle[areaIndex % colorArrayLength],
47153                     stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength]
47154                 }, areaIndex, store);
47155                 me.areas[areaIndex].setAttributes(rendererAttributes, true);
47156             }
47157         }
47158         me.renderLabels();
47159         me.renderCallouts();
47160     },
47161
47162     
47163     onAnimate: function(sprite, attr) {
47164         sprite.show();
47165         return this.callParent(arguments);
47166     },
47167
47168     
47169     onCreateLabel: function(storeItem, item, i, display) {
47170         var me = this,
47171             group = me.labelsGroup,
47172             config = me.label,
47173             bbox = me.bbox,
47174             endLabelStyle = Ext.apply(config, me.seriesLabelStyle);
47175
47176         return me.chart.surface.add(Ext.apply({
47177             'type': 'text',
47178             'text-anchor': 'middle',
47179             'group': group,
47180             'x': item.point[0],
47181             'y': bbox.y + bbox.height / 2
47182         }, endLabelStyle || {}));
47183     },
47184
47185     
47186     onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {
47187         var me = this,
47188             chart = me.chart,
47189             resizing = chart.resizing,
47190             config = me.label,
47191             format = config.renderer,
47192             field = config.field,
47193             bbox = me.bbox,
47194             x = item.point[0],
47195             y = item.point[1],
47196             bb, width, height;
47197
47198         label.setAttributes({
47199             text: format(storeItem.get(field[index])),
47200             hidden: true
47201         }, true);
47202
47203         bb = label.getBBox();
47204         width = bb.width / 2;
47205         height = bb.height / 2;
47206
47207         x = x - width < bbox.x? bbox.x + width : x;
47208         x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
47209         y = y - height < bbox.y? bbox.y + height : y;
47210         y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
47211
47212         if (me.chart.animate && !me.chart.resizing) {
47213             label.show(true);
47214             me.onAnimate(label, {
47215                 to: {
47216                     x: x,
47217                     y: y
47218                 }
47219             });
47220         } else {
47221             label.setAttributes({
47222                 x: x,
47223                 y: y
47224             }, true);
47225             if (resizing) {
47226                 me.animation.on('afteranimate', function() {
47227                     label.show(true);
47228                 });
47229             } else {
47230                 label.show(true);
47231             }
47232         }
47233     },
47234
47235     
47236     onPlaceCallout : function(callout, storeItem, item, i, display, animate, index) {
47237         var me = this,
47238             chart = me.chart,
47239             surface = chart.surface,
47240             resizing = chart.resizing,
47241             config = me.callouts,
47242             items = me.items,
47243             prev = (i == 0) ? false : items[i -1].point,
47244             next = (i == items.length -1) ? false : items[i +1].point,
47245             cur = item.point,
47246             dir, norm, normal, a, aprev, anext,
47247             bbox = callout.label.getBBox(),
47248             offsetFromViz = 30,
47249             offsetToSide = 10,
47250             offsetBox = 3,
47251             boxx, boxy, boxw, boxh,
47252             p, clipRect = me.clipRect,
47253             x, y;
47254
47255         
47256         if (!prev) {
47257             prev = cur;
47258         }
47259         if (!next) {
47260             next = cur;
47261         }
47262         a = (next[1] - prev[1]) / (next[0] - prev[0]);
47263         aprev = (cur[1] - prev[1]) / (cur[0] - prev[0]);
47264         anext = (next[1] - cur[1]) / (next[0] - cur[0]);
47265
47266         norm = Math.sqrt(1 + a * a);
47267         dir = [1 / norm, a / norm];
47268         normal = [-dir[1], dir[0]];
47269
47270         
47271         if (aprev > 0 && anext < 0 && normal[1] < 0 || aprev < 0 && anext > 0 && normal[1] > 0) {
47272             normal[0] *= -1;
47273             normal[1] *= -1;
47274         } else if (Math.abs(aprev) < Math.abs(anext) && normal[0] < 0 || Math.abs(aprev) > Math.abs(anext) && normal[0] > 0) {
47275             normal[0] *= -1;
47276             normal[1] *= -1;
47277         }
47278
47279         
47280         x = cur[0] + normal[0] * offsetFromViz;
47281         y = cur[1] + normal[1] * offsetFromViz;
47282
47283         
47284         boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
47285         boxy = y - bbox.height /2 - offsetBox;
47286         boxw = bbox.width + 2 * offsetBox;
47287         boxh = bbox.height + 2 * offsetBox;
47288
47289         
47290         
47291         if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) {
47292             normal[0] *= -1;
47293         }
47294         if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) {
47295             normal[1] *= -1;
47296         }
47297
47298         
47299         x = cur[0] + normal[0] * offsetFromViz;
47300         y = cur[1] + normal[1] * offsetFromViz;
47301
47302         
47303         boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
47304         boxy = y - bbox.height /2 - offsetBox;
47305         boxw = bbox.width + 2 * offsetBox;
47306         boxh = bbox.height + 2 * offsetBox;
47307
47308         
47309         callout.lines.setAttributes({
47310             path: ["M", cur[0], cur[1], "L", x, y, "Z"]
47311         }, true);
47312         
47313         callout.box.setAttributes({
47314             x: boxx,
47315             y: boxy,
47316             width: boxw,
47317             height: boxh
47318         }, true);
47319         
47320         callout.label.setAttributes({
47321             x: x + (normal[0] > 0? offsetBox : -(bbox.width + offsetBox)),
47322             y: y
47323         }, true);
47324         for (p in callout) {
47325             callout[p].show(true);
47326         }
47327     },
47328
47329     isItemInPoint: function(x, y, item, i) {
47330         var me = this,
47331             pointsUp = item.pointsUp,
47332             pointsDown = item.pointsDown,
47333             abs = Math.abs,
47334             dist = Infinity, p, pln, point;
47335
47336         for (p = 0, pln = pointsUp.length; p < pln; p++) {
47337             point = [pointsUp[p][0], pointsUp[p][1]];
47338             if (dist > abs(x - point[0])) {
47339                 dist = abs(x - point[0]);
47340             } else {
47341                 point = pointsUp[p -1];
47342                 if (y >= point[1] && (!pointsDown.length || y <= (pointsDown[p -1][1]))) {
47343                     item.storeIndex = p -1;
47344                     item.storeField = me.yField[i];
47345                     item.storeItem = me.chart.store.getAt(p -1);
47346                     item._points = pointsDown.length? [point, pointsDown[p -1]] : [point];
47347                     return true;
47348                 } else {
47349                     break;
47350                 }
47351             }
47352         }
47353         return false;
47354     },
47355
47356     
47357     highlightSeries: function() {
47358         var area, to, fillColor;
47359         if (this._index !== undefined) {
47360             area = this.areas[this._index];
47361             if (area.__highlightAnim) {
47362                 area.__highlightAnim.paused = true;
47363             }
47364             area.__highlighted = true;
47365             area.__prevOpacity = area.__prevOpacity || area.attr.opacity || 1;
47366             area.__prevFill = area.__prevFill || area.attr.fill;
47367             area.__prevLineWidth = area.__prevLineWidth || area.attr.lineWidth;
47368             fillColor = Ext.draw.Color.fromString(area.__prevFill);
47369             to = {
47370                 lineWidth: (area.__prevLineWidth || 0) + 2
47371             };
47372             if (fillColor) {
47373                 to.fill = fillColor.getLighter(0.2).toString();
47374             }
47375             else {
47376                 to.opacity = Math.max(area.__prevOpacity - 0.3, 0);
47377             }
47378             if (this.chart.animate) {
47379                 area.__highlightAnim = Ext.create('Ext.fx.Anim', Ext.apply({
47380                     target: area,
47381                     to: to
47382                 }, this.chart.animate));
47383             }
47384             else {
47385                 area.setAttributes(to, true);
47386             }
47387         }
47388     },
47389
47390     
47391     unHighlightSeries: function() {
47392         var area;
47393         if (this._index !== undefined) {
47394             area = this.areas[this._index];
47395             if (area.__highlightAnim) {
47396                 area.__highlightAnim.paused = true;
47397             }
47398             if (area.__highlighted) {
47399                 area.__highlighted = false;
47400                 area.__highlightAnim = Ext.create('Ext.fx.Anim', {
47401                     target: area,
47402                     to: {
47403                         fill: area.__prevFill,
47404                         opacity: area.__prevOpacity,
47405                         lineWidth: area.__prevLineWidth
47406                     }
47407                 });
47408             }
47409         }
47410     },
47411
47412     
47413     highlightItem: function(item) {
47414         var me = this,
47415             points, path;
47416         if (!item) {
47417             this.highlightSeries();
47418             return;
47419         }
47420         points = item._points;
47421         path = points.length == 2? ['M', points[0][0], points[0][1], 'L', points[1][0], points[1][1]]
47422                 : ['M', points[0][0], points[0][1], 'L', points[0][0], me.bbox.y + me.bbox.height];
47423         me.highlightSprite.setAttributes({
47424             path: path,
47425             hidden: false
47426         }, true);
47427     },
47428
47429     
47430     unHighlightItem: function(item) {
47431         if (!item) {
47432             this.unHighlightSeries();
47433         }
47434
47435         if (this.highlightSprite) {
47436             this.highlightSprite.hide(true);
47437         }
47438     },
47439
47440     
47441     hideAll: function() {
47442         if (!isNaN(this._index)) {
47443             this.__excludes[this._index] = true;
47444             this.areas[this._index].hide(true);
47445             this.drawSeries();
47446         }
47447     },
47448
47449     
47450     showAll: function() {
47451         if (!isNaN(this._index)) {
47452             this.__excludes[this._index] = false;
47453             this.areas[this._index].show(true);
47454             this.drawSeries();
47455         }
47456     },
47457
47458     
47459     getLegendColor: function(index) {
47460         var me = this;
47461         return me.colorArrayStyle[index % me.colorArrayStyle.length];
47462     }
47463 });
47464
47465 Ext.define('Ext.chart.series.Area', {
47466
47467     
47468
47469     extend: 'Ext.chart.series.Cartesian',
47470
47471     alias: 'series.area',
47472
47473     requires: ['Ext.chart.axis.Axis', 'Ext.draw.Color', 'Ext.fx.Anim'],
47474
47475     
47476
47477     type: 'area',
47478
47479     
47480     stacked: true,
47481
47482     
47483     style: {},
47484
47485     constructor: function(config) {
47486         this.callParent(arguments);
47487         var me = this,
47488             surface = me.chart.surface,
47489             i, l;
47490         Ext.apply(me, config, {
47491             __excludes: [],
47492             highlightCfg: {
47493                 lineWidth: 3,
47494                 stroke: '#55c',
47495                 opacity: 0.8,
47496                 color: '#f00'
47497             }
47498         });
47499         if (me.highlight) {
47500             me.highlightSprite = surface.add({
47501                 type: 'path',
47502                 path: ['M', 0, 0],
47503                 zIndex: 1000,
47504                 opacity: 0.3,
47505                 lineWidth: 5,
47506                 hidden: true,
47507                 stroke: '#444'
47508             });
47509         }
47510         me.group = surface.getGroup(me.seriesId);
47511     },
47512
47513     
47514     shrink: function(xValues, yValues, size) {
47515         var len = xValues.length,
47516             ratio = Math.floor(len / size),
47517             i, j,
47518             xSum = 0,
47519             yCompLen = this.areas.length,
47520             ySum = [],
47521             xRes = [],
47522             yRes = [];
47523         
47524         for (j = 0; j < yCompLen; ++j) {
47525             ySum[j] = 0;
47526         }
47527         for (i = 0; i < len; ++i) {
47528             xSum += xValues[i];
47529             for (j = 0; j < yCompLen; ++j) {
47530                 ySum[j] += yValues[i][j];
47531             }
47532             if (i % ratio == 0) {
47533                 
47534                 xRes.push(xSum/ratio);
47535                 for (j = 0; j < yCompLen; ++j) {
47536                     ySum[j] /= ratio;
47537                 }
47538                 yRes.push(ySum);
47539                 
47540                 xSum = 0;
47541                 for (j = 0, ySum = []; j < yCompLen; ++j) {
47542                     ySum[j] = 0;
47543                 }
47544             }
47545         }
47546         return {
47547             x: xRes,
47548             y: yRes
47549         };
47550     },
47551
47552     
47553     getBounds: function() {
47554         var me = this,
47555             chart = me.chart,
47556             store = chart.getChartStore(),
47557             areas = [].concat(me.yField),
47558             areasLen = areas.length,
47559             xValues = [],
47560             yValues = [],
47561             infinity = Infinity,
47562             minX = infinity,
47563             minY = infinity,
47564             maxX = -infinity,
47565             maxY = -infinity,
47566             math = Math,
47567             mmin = math.min,
47568             mmax = math.max,
47569             bbox, xScale, yScale, xValue, yValue, areaIndex, acumY, ln, sumValues, clipBox, areaElem;
47570
47571         me.setBBox();
47572         bbox = me.bbox;
47573
47574         
47575         if (me.axis) {
47576             axis = chart.axes.get(me.axis);
47577             if (axis) {
47578                 out = axis.calcEnds();
47579                 minY = out.from || axis.prevMin;
47580                 maxY = mmax(out.to || axis.prevMax, 0);
47581             }
47582         }
47583
47584         if (me.yField && !Ext.isNumber(minY)) {
47585             axis = Ext.create('Ext.chart.axis.Axis', {
47586                 chart: chart,
47587                 fields: [].concat(me.yField)
47588             });
47589             out = axis.calcEnds();
47590             minY = out.from || axis.prevMin;
47591             maxY = mmax(out.to || axis.prevMax, 0);
47592         }
47593
47594         if (!Ext.isNumber(minY)) {
47595             minY = 0;
47596         }
47597         if (!Ext.isNumber(maxY)) {
47598             maxY = 0;
47599         }
47600
47601         store.each(function(record, i) {
47602             xValue = record.get(me.xField);
47603             yValue = [];
47604             if (typeof xValue != 'number') {
47605                 xValue = i;
47606             }
47607             xValues.push(xValue);
47608             acumY = 0;
47609             for (areaIndex = 0; areaIndex < areasLen; areaIndex++) {
47610                 areaElem = record.get(areas[areaIndex]);
47611                 if (typeof areaElem == 'number') {
47612                     minY = mmin(minY, areaElem);
47613                     yValue.push(areaElem);
47614                     acumY += areaElem;
47615                 }
47616             }
47617             minX = mmin(minX, xValue);
47618             maxX = mmax(maxX, xValue);
47619             maxY = mmax(maxY, acumY);
47620             yValues.push(yValue);
47621         }, me);
47622
47623         xScale = bbox.width / ((maxX - minX) || 1);
47624         yScale = bbox.height / ((maxY - minY) || 1);
47625
47626         ln = xValues.length;
47627         if ((ln > bbox.width) && me.areas) {
47628             sumValues = me.shrink(xValues, yValues, bbox.width);
47629             xValues = sumValues.x;
47630             yValues = sumValues.y;
47631         }
47632
47633         return {
47634             bbox: bbox,
47635             minX: minX,
47636             minY: minY,
47637             xValues: xValues,
47638             yValues: yValues,
47639             xScale: xScale,
47640             yScale: yScale,
47641             areasLen: areasLen
47642         };
47643     },
47644
47645     
47646     getPaths: function() {
47647         var me = this,
47648             chart = me.chart,
47649             store = chart.getChartStore(),
47650             first = true,
47651             bounds = me.getBounds(),
47652             bbox = bounds.bbox,
47653             items = me.items = [],
47654             componentPaths = [],
47655             componentPath,
47656             paths = [],
47657             i, ln, x, y, xValue, yValue, acumY, areaIndex, prevAreaIndex, areaElem, path;
47658
47659         ln = bounds.xValues.length;
47660         
47661         for (i = 0; i < ln; i++) {
47662             xValue = bounds.xValues[i];
47663             yValue = bounds.yValues[i];
47664             x = bbox.x + (xValue - bounds.minX) * bounds.xScale;
47665             acumY = 0;
47666             for (areaIndex = 0; areaIndex < bounds.areasLen; areaIndex++) {
47667                 
47668                 if (me.__excludes[areaIndex]) {
47669                     continue;
47670                 }
47671                 if (!componentPaths[areaIndex]) {
47672                     componentPaths[areaIndex] = [];
47673                 }
47674                 areaElem = yValue[areaIndex];
47675                 acumY += areaElem;
47676                 y = bbox.y + bbox.height - (acumY - bounds.minY) * bounds.yScale;
47677                 if (!paths[areaIndex]) {
47678                     paths[areaIndex] = ['M', x, y];
47679                     componentPaths[areaIndex].push(['L', x, y]);
47680                 } else {
47681                     paths[areaIndex].push('L', x, y);
47682                     componentPaths[areaIndex].push(['L', x, y]);
47683                 }
47684                 if (!items[areaIndex]) {
47685                     items[areaIndex] = {
47686                         pointsUp: [],
47687                         pointsDown: [],
47688                         series: me
47689                     };
47690                 }
47691                 items[areaIndex].pointsUp.push([x, y]);
47692             }
47693         }
47694
47695         
47696         for (areaIndex = 0; areaIndex < bounds.areasLen; areaIndex++) {
47697             
47698             if (me.__excludes[areaIndex]) {
47699                 continue;
47700             }
47701             path = paths[areaIndex];
47702             
47703             if (areaIndex == 0 || first) {
47704                 first = false;
47705                 path.push('L', x, bbox.y + bbox.height,
47706                           'L', bbox.x, bbox.y + bbox.height,
47707                           'Z');
47708             }
47709             
47710             else {
47711                 componentPath = componentPaths[prevAreaIndex];
47712                 componentPath.reverse();
47713                 path.push('L', x, componentPath[0][2]);
47714                 for (i = 0; i < ln; i++) {
47715                     path.push(componentPath[i][0],
47716                               componentPath[i][1],
47717                               componentPath[i][2]);
47718                     items[areaIndex].pointsDown[ln -i -1] = [componentPath[i][1], componentPath[i][2]];
47719                 }
47720                 path.push('L', bbox.x, path[2], 'Z');
47721             }
47722             prevAreaIndex = areaIndex;
47723         }
47724         return {
47725             paths: paths,
47726             areasLen: bounds.areasLen
47727         };
47728     },
47729
47730     
47731     drawSeries: function() {
47732         var me = this,
47733             chart = me.chart,
47734             store = chart.getChartStore(),
47735             surface = chart.surface,
47736             animate = chart.animate,
47737             group = me.group,
47738             endLineStyle = Ext.apply(me.seriesStyle, me.style),
47739             colorArrayStyle = me.colorArrayStyle,
47740             colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
47741             areaIndex, areaElem, paths, path, rendererAttributes;
47742
47743         me.unHighlightItem();
47744         me.cleanHighlights();
47745
47746         if (!store || !store.getCount()) {
47747             return;
47748         }
47749
47750         paths = me.getPaths();
47751
47752         if (!me.areas) {
47753             me.areas = [];
47754         }
47755
47756         for (areaIndex = 0; areaIndex < paths.areasLen; areaIndex++) {
47757             
47758             if (me.__excludes[areaIndex]) {
47759                 continue;
47760             }
47761             if (!me.areas[areaIndex]) {
47762                 me.items[areaIndex].sprite = me.areas[areaIndex] = surface.add(Ext.apply({}, {
47763                     type: 'path',
47764                     group: group,
47765                     
47766                     path: paths.paths[areaIndex],
47767                     stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength],
47768                     fill: colorArrayStyle[areaIndex % colorArrayLength]
47769                 }, endLineStyle || {}));
47770             }
47771             areaElem = me.areas[areaIndex];
47772             path = paths.paths[areaIndex];
47773             if (animate) {
47774                 
47775                 rendererAttributes = me.renderer(areaElem, false, {
47776                     path: path,
47777                     
47778                     fill: colorArrayStyle[areaIndex % colorArrayLength],
47779                     stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength]
47780                 }, areaIndex, store);
47781                 
47782                 me.animation = me.onAnimate(areaElem, {
47783                     to: rendererAttributes
47784                 });
47785             } else {
47786                 rendererAttributes = me.renderer(areaElem, false, {
47787                     path: path,
47788                     
47789                     hidden: false,
47790                     fill: colorArrayStyle[areaIndex % colorArrayLength],
47791                     stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength]
47792                 }, areaIndex, store);
47793                 me.areas[areaIndex].setAttributes(rendererAttributes, true);
47794             }
47795         }
47796         me.renderLabels();
47797         me.renderCallouts();
47798     },
47799
47800     
47801     onAnimate: function(sprite, attr) {
47802         sprite.show();
47803         return this.callParent(arguments);
47804     },
47805
47806     
47807     onCreateLabel: function(storeItem, item, i, display) {
47808         var me = this,
47809             group = me.labelsGroup,
47810             config = me.label,
47811             bbox = me.bbox,
47812             endLabelStyle = Ext.apply(config, me.seriesLabelStyle);
47813
47814         return me.chart.surface.add(Ext.apply({
47815             'type': 'text',
47816             'text-anchor': 'middle',
47817             'group': group,
47818             'x': item.point[0],
47819             'y': bbox.y + bbox.height / 2
47820         }, endLabelStyle || {}));
47821     },
47822
47823     
47824     onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {
47825         var me = this,
47826             chart = me.chart,
47827             resizing = chart.resizing,
47828             config = me.label,
47829             format = config.renderer,
47830             field = config.field,
47831             bbox = me.bbox,
47832             x = item.point[0],
47833             y = item.point[1],
47834             bb, width, height;
47835
47836         label.setAttributes({
47837             text: format(storeItem.get(field[index])),
47838             hidden: true
47839         }, true);
47840
47841         bb = label.getBBox();
47842         width = bb.width / 2;
47843         height = bb.height / 2;
47844
47845         x = x - width < bbox.x? bbox.x + width : x;
47846         x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
47847         y = y - height < bbox.y? bbox.y + height : y;
47848         y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
47849
47850         if (me.chart.animate && !me.chart.resizing) {
47851             label.show(true);
47852             me.onAnimate(label, {
47853                 to: {
47854                     x: x,
47855                     y: y
47856                 }
47857             });
47858         } else {
47859             label.setAttributes({
47860                 x: x,
47861                 y: y
47862             }, true);
47863             if (resizing) {
47864                 me.animation.on('afteranimate', function() {
47865                     label.show(true);
47866                 });
47867             } else {
47868                 label.show(true);
47869             }
47870         }
47871     },
47872
47873     
47874     onPlaceCallout : function(callout, storeItem, item, i, display, animate, index) {
47875         var me = this,
47876             chart = me.chart,
47877             surface = chart.surface,
47878             resizing = chart.resizing,
47879             config = me.callouts,
47880             items = me.items,
47881             prev = (i == 0) ? false : items[i -1].point,
47882             next = (i == items.length -1) ? false : items[i +1].point,
47883             cur = item.point,
47884             dir, norm, normal, a, aprev, anext,
47885             bbox = callout.label.getBBox(),
47886             offsetFromViz = 30,
47887             offsetToSide = 10,
47888             offsetBox = 3,
47889             boxx, boxy, boxw, boxh,
47890             p, clipRect = me.clipRect,
47891             x, y;
47892
47893         
47894         if (!prev) {
47895             prev = cur;
47896         }
47897         if (!next) {
47898             next = cur;
47899         }
47900         a = (next[1] - prev[1]) / (next[0] - prev[0]);
47901         aprev = (cur[1] - prev[1]) / (cur[0] - prev[0]);
47902         anext = (next[1] - cur[1]) / (next[0] - cur[0]);
47903
47904         norm = Math.sqrt(1 + a * a);
47905         dir = [1 / norm, a / norm];
47906         normal = [-dir[1], dir[0]];
47907
47908         
47909         if (aprev > 0 && anext < 0 && normal[1] < 0 || aprev < 0 && anext > 0 && normal[1] > 0) {
47910             normal[0] *= -1;
47911             normal[1] *= -1;
47912         } else if (Math.abs(aprev) < Math.abs(anext) && normal[0] < 0 || Math.abs(aprev) > Math.abs(anext) && normal[0] > 0) {
47913             normal[0] *= -1;
47914             normal[1] *= -1;
47915         }
47916
47917         
47918         x = cur[0] + normal[0] * offsetFromViz;
47919         y = cur[1] + normal[1] * offsetFromViz;
47920
47921         
47922         boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
47923         boxy = y - bbox.height /2 - offsetBox;
47924         boxw = bbox.width + 2 * offsetBox;
47925         boxh = bbox.height + 2 * offsetBox;
47926
47927         
47928         
47929         if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) {
47930             normal[0] *= -1;
47931         }
47932         if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) {
47933             normal[1] *= -1;
47934         }
47935
47936         
47937         x = cur[0] + normal[0] * offsetFromViz;
47938         y = cur[1] + normal[1] * offsetFromViz;
47939
47940         
47941         boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
47942         boxy = y - bbox.height /2 - offsetBox;
47943         boxw = bbox.width + 2 * offsetBox;
47944         boxh = bbox.height + 2 * offsetBox;
47945
47946         
47947         callout.lines.setAttributes({
47948             path: ["M", cur[0], cur[1], "L", x, y, "Z"]
47949         }, true);
47950         
47951         callout.box.setAttributes({
47952             x: boxx,
47953             y: boxy,
47954             width: boxw,
47955             height: boxh
47956         }, true);
47957         
47958         callout.label.setAttributes({
47959             x: x + (normal[0] > 0? offsetBox : -(bbox.width + offsetBox)),
47960             y: y
47961         }, true);
47962         for (p in callout) {
47963             callout[p].show(true);
47964         }
47965     },
47966
47967     isItemInPoint: function(x, y, item, i) {
47968         var me = this,
47969             pointsUp = item.pointsUp,
47970             pointsDown = item.pointsDown,
47971             abs = Math.abs,
47972             dist = Infinity, p, pln, point;
47973
47974         for (p = 0, pln = pointsUp.length; p < pln; p++) {
47975             point = [pointsUp[p][0], pointsUp[p][1]];
47976             if (dist > abs(x - point[0])) {
47977                 dist = abs(x - point[0]);
47978             } else {
47979                 point = pointsUp[p -1];
47980                 if (y >= point[1] && (!pointsDown.length || y <= (pointsDown[p -1][1]))) {
47981                     item.storeIndex = p -1;
47982                     item.storeField = me.yField[i];
47983                     item.storeItem = me.chart.store.getAt(p -1);
47984                     item._points = pointsDown.length? [point, pointsDown[p -1]] : [point];
47985                     return true;
47986                 } else {
47987                     break;
47988                 }
47989             }
47990         }
47991         return false;
47992     },
47993
47994     
47995     highlightSeries: function() {
47996         var area, to, fillColor;
47997         if (this._index !== undefined) {
47998             area = this.areas[this._index];
47999             if (area.__highlightAnim) {
48000                 area.__highlightAnim.paused = true;
48001             }
48002             area.__highlighted = true;
48003             area.__prevOpacity = area.__prevOpacity || area.attr.opacity || 1;
48004             area.__prevFill = area.__prevFill || area.attr.fill;
48005             area.__prevLineWidth = area.__prevLineWidth || area.attr.lineWidth;
48006             fillColor = Ext.draw.Color.fromString(area.__prevFill);
48007             to = {
48008                 lineWidth: (area.__prevLineWidth || 0) + 2
48009             };
48010             if (fillColor) {
48011                 to.fill = fillColor.getLighter(0.2).toString();
48012             }
48013             else {
48014                 to.opacity = Math.max(area.__prevOpacity - 0.3, 0);
48015             }
48016             if (this.chart.animate) {
48017                 area.__highlightAnim = Ext.create('Ext.fx.Anim', Ext.apply({
48018                     target: area,
48019                     to: to
48020                 }, this.chart.animate));
48021             }
48022             else {
48023                 area.setAttributes(to, true);
48024             }
48025         }
48026     },
48027
48028     
48029     unHighlightSeries: function() {
48030         var area;
48031         if (this._index !== undefined) {
48032             area = this.areas[this._index];
48033             if (area.__highlightAnim) {
48034                 area.__highlightAnim.paused = true;
48035             }
48036             if (area.__highlighted) {
48037                 area.__highlighted = false;
48038                 area.__highlightAnim = Ext.create('Ext.fx.Anim', {
48039                     target: area,
48040                     to: {
48041                         fill: area.__prevFill,
48042                         opacity: area.__prevOpacity,
48043                         lineWidth: area.__prevLineWidth
48044                     }
48045                 });
48046             }
48047         }
48048     },
48049
48050     
48051     highlightItem: function(item) {
48052         var me = this,
48053             points, path;
48054         if (!item) {
48055             this.highlightSeries();
48056             return;
48057         }
48058         points = item._points;
48059         path = points.length == 2? ['M', points[0][0], points[0][1], 'L', points[1][0], points[1][1]]
48060                 : ['M', points[0][0], points[0][1], 'L', points[0][0], me.bbox.y + me.bbox.height];
48061         me.highlightSprite.setAttributes({
48062             path: path,
48063             hidden: false
48064         }, true);
48065     },
48066
48067     
48068     unHighlightItem: function(item) {
48069         if (!item) {
48070             this.unHighlightSeries();
48071         }
48072
48073         if (this.highlightSprite) {
48074             this.highlightSprite.hide(true);
48075         }
48076     },
48077
48078     
48079     hideAll: function() {
48080         if (!isNaN(this._index)) {
48081             this.__excludes[this._index] = true;
48082             this.areas[this._index].hide(true);
48083             this.drawSeries();
48084         }
48085     },
48086
48087     
48088     showAll: function() {
48089         if (!isNaN(this._index)) {
48090             this.__excludes[this._index] = false;
48091             this.areas[this._index].show(true);
48092             this.drawSeries();
48093         }
48094     },
48095
48096     
48097     getLegendColor: function(index) {
48098         var me = this;
48099         return me.colorArrayStyle[index % me.colorArrayStyle.length];
48100     }
48101 });
48102
48103
48104 Ext.define('Ext.chart.series.Bar', {
48105
48106     
48107
48108     extend: 'Ext.chart.series.Cartesian',
48109
48110     alternateClassName: ['Ext.chart.BarSeries', 'Ext.chart.BarChart', 'Ext.chart.StackedBarChart'],
48111
48112     requires: ['Ext.chart.axis.Axis', 'Ext.fx.Anim'],
48113
48114     
48115
48116     type: 'bar',
48117
48118     alias: 'series.bar',
48119     
48120     column: false,
48121
48122     
48123     style: {},
48124
48125     
48126     gutter: 38.2,
48127
48128     
48129     groupGutter: 38.2,
48130
48131     
48132     xPadding: 0,
48133
48134     
48135     yPadding: 10,
48136
48137     constructor: function(config) {
48138         this.callParent(arguments);
48139         var me = this,
48140             surface = me.chart.surface,
48141             shadow = me.chart.shadow,
48142             i, l;
48143         Ext.apply(me, config, {
48144             highlightCfg: {
48145                 lineWidth: 3,
48146                 stroke: '#55c',
48147                 opacity: 0.8,
48148                 color: '#f00'
48149             },
48150
48151             shadowAttributes: [{
48152                 "stroke-width": 6,
48153                 "stroke-opacity": 0.05,
48154                 stroke: 'rgb(200, 200, 200)',
48155                 translate: {
48156                     x: 1.2,
48157                     y: 1.2
48158                 }
48159             }, {
48160                 "stroke-width": 4,
48161                 "stroke-opacity": 0.1,
48162                 stroke: 'rgb(150, 150, 150)',
48163                 translate: {
48164                     x: 0.9,
48165                     y: 0.9
48166                 }
48167             }, {
48168                 "stroke-width": 2,
48169                 "stroke-opacity": 0.15,
48170                 stroke: 'rgb(100, 100, 100)',
48171                 translate: {
48172                     x: 0.6,
48173                     y: 0.6
48174                 }
48175             }]
48176         });
48177         me.group = surface.getGroup(me.seriesId + '-bars');
48178         if (shadow) {
48179             for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
48180                 me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
48181             }
48182         }
48183     },
48184
48185     
48186     getBarGirth: function() {
48187         var me = this,
48188             store = me.chart.getChartStore(),
48189             column = me.column,
48190             ln = store.getCount(),
48191             gutter = me.gutter / 100;
48192
48193         return (me.chart.chartBBox[column ? 'width' : 'height'] - me[column ? 'xPadding' : 'yPadding'] * 2) / (ln * (gutter + 1) - gutter);
48194     },
48195
48196     
48197     getGutters: function() {
48198         var me = this,
48199             column = me.column,
48200             gutter = Math.ceil(me[column ? 'xPadding' : 'yPadding'] + me.getBarGirth() / 2);
48201         return me.column ? [gutter, 0] : [0, gutter];
48202     },
48203
48204     
48205     getBounds: function() {
48206         var me = this,
48207             chart = me.chart,
48208             store = chart.getChartStore(),
48209             bars = [].concat(me.yField),
48210             barsLen = bars.length,
48211             groupBarsLen = barsLen,
48212             groupGutter = me.groupGutter / 100,
48213             column = me.column,
48214             xPadding = me.xPadding,
48215             yPadding = me.yPadding,
48216             stacked = me.stacked,
48217             barWidth = me.getBarGirth(),
48218             math = Math,
48219             mmax = math.max,
48220             mabs = math.abs,
48221             groupBarWidth, bbox, minY, maxY, axis, out,
48222             scale, zero, total, rec, j, plus, minus;
48223
48224         me.setBBox(true);
48225         bbox = me.bbox;
48226
48227         
48228         if (me.__excludes) {
48229             for (j = 0, total = me.__excludes.length; j < total; j++) {
48230                 if (me.__excludes[j]) {
48231                     groupBarsLen--;
48232                 }
48233             }
48234         }
48235
48236         if (me.axis) {
48237             axis = chart.axes.get(me.axis);
48238             if (axis) {
48239                 out = axis.calcEnds();
48240                 minY = out.from;
48241                 maxY = out.to;
48242             }
48243         }
48244
48245         if (me.yField && !Ext.isNumber(minY)) {
48246             axis = Ext.create('Ext.chart.axis.Axis', {
48247                 chart: chart,
48248                 fields: [].concat(me.yField)
48249             });
48250             out = axis.calcEnds();
48251             minY = out.from;
48252             maxY = out.to;
48253         }
48254
48255         if (!Ext.isNumber(minY)) {
48256             minY = 0;
48257         }
48258         if (!Ext.isNumber(maxY)) {
48259             maxY = 0;
48260         }
48261         scale = (column ? bbox.height - yPadding * 2 : bbox.width - xPadding * 2) / (maxY - minY);
48262         groupBarWidth = barWidth / ((stacked ? 1 : groupBarsLen) * (groupGutter + 1) - groupGutter);
48263         zero = (column) ? bbox.y + bbox.height - yPadding : bbox.x + xPadding;
48264
48265         if (stacked) {
48266             total = [[], []];
48267             store.each(function(record, i) {
48268                 total[0][i] = total[0][i] || 0;
48269                 total[1][i] = total[1][i] || 0;
48270                 for (j = 0; j < barsLen; j++) {
48271                     if (me.__excludes && me.__excludes[j]) {
48272                         continue;
48273                     }
48274                     rec = record.get(bars[j]);
48275                     total[+(rec > 0)][i] += mabs(rec);
48276                 }
48277             });
48278             total[+(maxY > 0)].push(mabs(maxY));
48279             total[+(minY > 0)].push(mabs(minY));
48280             minus = mmax.apply(math, total[0]);
48281             plus = mmax.apply(math, total[1]);
48282             scale = (column ? bbox.height - yPadding * 2 : bbox.width - xPadding * 2) / (plus + minus);
48283             zero = zero + minus * scale * (column ? -1 : 1);
48284         }
48285         else if (minY / maxY < 0) {
48286             zero = zero - minY * scale * (column ? -1 : 1);
48287         }
48288         return {
48289             bars: bars,
48290             bbox: bbox,
48291             barsLen: barsLen,
48292             groupBarsLen: groupBarsLen,
48293             barWidth: barWidth,
48294             groupBarWidth: groupBarWidth,
48295             scale: scale,
48296             zero: zero,
48297             xPadding: xPadding,
48298             yPadding: yPadding,
48299             signed: minY / maxY < 0,
48300             minY: minY,
48301             maxY: maxY
48302         };
48303     },
48304
48305     
48306     getPaths: function() {
48307         var me = this,
48308             chart = me.chart,
48309             store = chart.getChartStore(),
48310             bounds = me.bounds = me.getBounds(),
48311             items = me.items = [],
48312             gutter = me.gutter / 100,
48313             groupGutter = me.groupGutter / 100,
48314             animate = chart.animate,
48315             column = me.column,
48316             group = me.group,
48317             enableShadows = chart.shadow,
48318             shadowGroups = me.shadowGroups,
48319             shadowAttributes = me.shadowAttributes,
48320             shadowGroupsLn = shadowGroups.length,
48321             bbox = bounds.bbox,
48322             xPadding = me.xPadding,
48323             yPadding = me.yPadding,
48324             stacked = me.stacked,
48325             barsLen = bounds.barsLen,
48326             colors = me.colorArrayStyle,
48327             colorLength = colors && colors.length || 0,
48328             math = Math,
48329             mmax = math.max,
48330             mmin = math.min,
48331             mabs = math.abs,
48332             j, yValue, height, totalDim, totalNegDim, bottom, top, hasShadow, barAttr, attrs, counter,
48333             shadowIndex, shadow, sprite, offset, floorY;
48334
48335         store.each(function(record, i, total) {
48336             bottom = bounds.zero;
48337             top = bounds.zero;
48338             totalDim = 0;
48339             totalNegDim = 0;
48340             hasShadow = false;
48341             for (j = 0, counter = 0; j < barsLen; j++) {
48342                 
48343                 if (me.__excludes && me.__excludes[j]) {
48344                     continue;
48345                 }
48346                 yValue = record.get(bounds.bars[j]);
48347                 height = Math.round((yValue - mmax(bounds.minY, 0)) * bounds.scale);
48348                 barAttr = {
48349                     fill: colors[(barsLen > 1 ? j : 0) % colorLength]
48350                 };
48351                 if (column) {
48352                     Ext.apply(barAttr, {
48353                         height: height,
48354                         width: mmax(bounds.groupBarWidth, 0),
48355                         x: (bbox.x + xPadding + i * bounds.barWidth * (1 + gutter) + counter * bounds.groupBarWidth * (1 + groupGutter) * !stacked),
48356                         y: bottom - height
48357                     });
48358                 }
48359                 else {
48360                     
48361                     offset = (total - 1) - i;
48362                     Ext.apply(barAttr, {
48363                         height: mmax(bounds.groupBarWidth, 0),
48364                         width: height + (bottom == bounds.zero),
48365                         x: bottom + (bottom != bounds.zero),
48366                         y: (bbox.y + yPadding + offset * bounds.barWidth * (1 + gutter) + counter * bounds.groupBarWidth * (1 + groupGutter) * !stacked + 1)
48367                     });
48368                 }
48369                 if (height < 0) {
48370                     if (column) {
48371                         barAttr.y = top;
48372                         barAttr.height = mabs(height);
48373                     } else {
48374                         barAttr.x = top + height;
48375                         barAttr.width = mabs(height);
48376                     }
48377                 }
48378                 if (stacked) {
48379                     if (height < 0) {
48380                         top += height * (column ? -1 : 1);
48381                     } else {
48382                         bottom += height * (column ? -1 : 1);
48383                     }
48384                     totalDim += mabs(height);
48385                     if (height < 0) {
48386                         totalNegDim += mabs(height);
48387                     }
48388                 }
48389                 barAttr.x = Math.floor(barAttr.x) + 1;
48390                 floorY = Math.floor(barAttr.y);
48391                 if (!Ext.isIE9 && barAttr.y > floorY) {
48392                     floorY--;
48393                 }
48394                 barAttr.y = floorY;
48395                 barAttr.width = Math.floor(barAttr.width);
48396                 barAttr.height = Math.floor(barAttr.height);
48397                 items.push({
48398                     series: me,
48399                     storeItem: record,
48400                     value: [record.get(me.xField), yValue],
48401                     attr: barAttr,
48402                     point: column ? [barAttr.x + barAttr.width / 2, yValue >= 0 ? barAttr.y : barAttr.y + barAttr.height] :
48403                                     [yValue >= 0 ? barAttr.x + barAttr.width : barAttr.x, barAttr.y + barAttr.height / 2]
48404                 });
48405                 
48406                 if (animate && chart.resizing) {
48407                     attrs = column ? {
48408                         x: barAttr.x,
48409                         y: bounds.zero,
48410                         width: barAttr.width,
48411                         height: 0
48412                     } : {
48413                         x: bounds.zero,
48414                         y: barAttr.y,
48415                         width: 0,
48416                         height: barAttr.height
48417                     };
48418                     if (enableShadows && (stacked && !hasShadow || !stacked)) {
48419                         hasShadow = true;
48420                         
48421                         for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
48422                             shadow = shadowGroups[shadowIndex].getAt(stacked ? i : (i * barsLen + j));
48423                             if (shadow) {
48424                                 shadow.setAttributes(attrs, true);
48425                             }
48426                         }
48427                     }
48428                     
48429                     sprite = group.getAt(i * barsLen + j);
48430                     if (sprite) {
48431                         sprite.setAttributes(attrs, true);
48432                     }
48433                 }
48434                 counter++;
48435             }
48436             if (stacked && items.length) {
48437                 items[i * counter].totalDim = totalDim;
48438                 items[i * counter].totalNegDim = totalNegDim;
48439             }
48440         }, me);
48441     },
48442
48443     
48444     renderShadows: function(i, barAttr, baseAttrs, bounds) {
48445         var me = this,
48446             chart = me.chart,
48447             surface = chart.surface,
48448             animate = chart.animate,
48449             stacked = me.stacked,
48450             shadowGroups = me.shadowGroups,
48451             shadowAttributes = me.shadowAttributes,
48452             shadowGroupsLn = shadowGroups.length,
48453             store = chart.getChartStore(),
48454             column = me.column,
48455             items = me.items,
48456             shadows = [],
48457             zero = bounds.zero,
48458             shadowIndex, shadowBarAttr, shadow, totalDim, totalNegDim, j, rendererAttributes;
48459
48460         if ((stacked && (i % bounds.groupBarsLen === 0)) || !stacked) {
48461             j = i / bounds.groupBarsLen;
48462             
48463             for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
48464                 shadowBarAttr = Ext.apply({}, shadowAttributes[shadowIndex]);
48465                 shadow = shadowGroups[shadowIndex].getAt(stacked ? j : i);
48466                 Ext.copyTo(shadowBarAttr, barAttr, 'x,y,width,height');
48467                 if (!shadow) {
48468                     shadow = surface.add(Ext.apply({
48469                         type: 'rect',
48470                         group: shadowGroups[shadowIndex]
48471                     }, Ext.apply({}, baseAttrs, shadowBarAttr)));
48472                 }
48473                 if (stacked) {
48474                     totalDim = items[i].totalDim;
48475                     totalNegDim = items[i].totalNegDim;
48476                     if (column) {
48477                         shadowBarAttr.y = zero - totalNegDim;
48478                         shadowBarAttr.height = totalDim;
48479                     }
48480                     else {
48481                         shadowBarAttr.x = zero - totalNegDim;
48482                         shadowBarAttr.width = totalDim;
48483                     }
48484                 }
48485                 if (animate) {
48486                     if (!stacked) {
48487                         rendererAttributes = me.renderer(shadow, store.getAt(j), shadowBarAttr, i, store);
48488                         me.onAnimate(shadow, { to: rendererAttributes });
48489                     }
48490                     else {
48491                         rendererAttributes = me.renderer(shadow, store.getAt(j), Ext.apply(shadowBarAttr, { hidden: true }), i, store);
48492                         shadow.setAttributes(rendererAttributes, true);
48493                     }
48494                 }
48495                 else {
48496                     rendererAttributes = me.renderer(shadow, store.getAt(j), Ext.apply(shadowBarAttr, { hidden: false }), i, store);
48497                     shadow.setAttributes(rendererAttributes, true);
48498                 }
48499                 shadows.push(shadow);
48500             }
48501         }
48502         return shadows;
48503     },
48504
48505     
48506     drawSeries: function() {
48507         var me = this,
48508             chart = me.chart,
48509             store = chart.getChartStore(),
48510             surface = chart.surface,
48511             animate = chart.animate,
48512             stacked = me.stacked,
48513             column = me.column,
48514             enableShadows = chart.shadow,
48515             shadowGroups = me.shadowGroups,
48516             shadowGroupsLn = shadowGroups.length,
48517             group = me.group,
48518             seriesStyle = me.seriesStyle,
48519             items, ln, i, j, baseAttrs, sprite, rendererAttributes, shadowIndex, shadowGroup,
48520             bounds, endSeriesStyle, barAttr, attrs, anim;
48521
48522         if (!store || !store.getCount()) {
48523             return;
48524         }
48525
48526         
48527         delete seriesStyle.fill;
48528         endSeriesStyle = Ext.apply(seriesStyle, this.style);
48529         me.unHighlightItem();
48530         me.cleanHighlights();
48531
48532         me.getPaths();
48533         bounds = me.bounds;
48534         items = me.items;
48535
48536         baseAttrs = column ? {
48537             y: bounds.zero,
48538             height: 0
48539         } : {
48540             x: bounds.zero,
48541             width: 0
48542         };
48543         ln = items.length;
48544         
48545         for (i = 0; i < ln; i++) {
48546             sprite = group.getAt(i);
48547             barAttr = items[i].attr;
48548
48549             if (enableShadows) {
48550                 items[i].shadows = me.renderShadows(i, barAttr, baseAttrs, bounds);
48551             }
48552
48553             
48554             if (!sprite) {
48555                 attrs = Ext.apply({}, baseAttrs, barAttr);
48556                 attrs = Ext.apply(attrs, endSeriesStyle || {});
48557                 sprite = surface.add(Ext.apply({}, {
48558                     type: 'rect',
48559                     group: group
48560                 }, attrs));
48561             }
48562             if (animate) {
48563                 rendererAttributes = me.renderer(sprite, store.getAt(i), barAttr, i, store);
48564                 sprite._to = rendererAttributes;
48565                 anim = me.onAnimate(sprite, { to: Ext.apply(rendererAttributes, endSeriesStyle) });
48566                 if (enableShadows && stacked && (i % bounds.barsLen === 0)) {
48567                     j = i / bounds.barsLen;
48568                     for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
48569                         anim.on('afteranimate', function() {
48570                             this.show(true);
48571                         }, shadowGroups[shadowIndex].getAt(j));
48572                     }
48573                 }
48574             }
48575             else {
48576                 rendererAttributes = me.renderer(sprite, store.getAt(i), Ext.apply(barAttr, { hidden: false }), i, store);
48577                 sprite.setAttributes(Ext.apply(rendererAttributes, endSeriesStyle), true);
48578             }
48579             items[i].sprite = sprite;
48580         }
48581
48582         
48583         ln = group.getCount();
48584         for (j = i; j < ln; j++) {
48585             group.getAt(j).hide(true);
48586         }
48587         
48588         if (enableShadows) {
48589             for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
48590                 shadowGroup = shadowGroups[shadowIndex];
48591                 ln = shadowGroup.getCount();
48592                 for (j = i; j < ln; j++) {
48593                     shadowGroup.getAt(j).hide(true);
48594                 }
48595             }
48596         }
48597         me.renderLabels();
48598     },
48599
48600     
48601     onCreateLabel: function(storeItem, item, i, display) {
48602         var me = this,
48603             surface = me.chart.surface,
48604             group = me.labelsGroup,
48605             config = me.label,
48606             endLabelStyle = Ext.apply({}, config, me.seriesLabelStyle || {}),
48607             sprite;
48608         return surface.add(Ext.apply({
48609             type: 'text',
48610             group: group
48611         }, endLabelStyle || {}));
48612     },
48613
48614     
48615     onPlaceLabel: function(label, storeItem, item, i, display, animate, j, index) {
48616         
48617         
48618         var me = this,
48619             opt = me.bounds,
48620             groupBarWidth = opt.groupBarWidth,
48621             column = me.column,
48622             chart = me.chart,
48623             chartBBox = chart.chartBBox,
48624             resizing = chart.resizing,
48625             xValue = item.value[0],
48626             yValue = item.value[1],
48627             attr = item.attr,
48628             config = me.label,
48629             rotate = config.orientation == 'vertical',
48630             field = [].concat(config.field),
48631             format = config.renderer,
48632             text = format(storeItem.get(field[index])),
48633             size = me.getLabelSize(text),
48634             width = size.width,
48635             height = size.height,
48636             zero = opt.zero,
48637             outside = 'outside',
48638             insideStart = 'insideStart',
48639             insideEnd = 'insideEnd',
48640             offsetX = 10,
48641             offsetY = 6,
48642             signed = opt.signed,
48643             x, y, finalAttr;
48644
48645         label.setAttributes({
48646             text: text
48647         });
48648
48649         label.isOutside = false;
48650         if (column) {
48651             if (display == outside) {
48652                 if (height + offsetY + attr.height > (yValue >= 0 ? zero - chartBBox.y : chartBBox.y + chartBBox.height - zero)) {
48653                     display = insideEnd;
48654                 }
48655             } else {
48656                 if (height + offsetY > attr.height) {
48657                     display = outside;
48658                     label.isOutside = true;
48659                 }
48660             }
48661             x = attr.x + groupBarWidth / 2;
48662             y = display == insideStart ?
48663                     (zero + ((height / 2 + 3) * (yValue >= 0 ? -1 : 1))) :
48664                     (yValue >= 0 ? (attr.y + ((height / 2 + 3) * (display == outside ? -1 : 1))) :
48665                                    (attr.y + attr.height + ((height / 2 + 3) * (display === outside ? 1 : -1))));
48666         }
48667         else {
48668             if (display == outside) {
48669                 if (width + offsetX + attr.width > (yValue >= 0 ? chartBBox.x + chartBBox.width - zero : zero - chartBBox.x)) {
48670                     display = insideEnd;
48671                 }
48672             }
48673             else {
48674                 if (width + offsetX > attr.width) {
48675                     display = outside;
48676                     label.isOutside = true;
48677                 }
48678             }
48679             x = display == insideStart ?
48680                 (zero + ((width / 2 + 5) * (yValue >= 0 ? 1 : -1))) :
48681                 (yValue >= 0 ? (attr.x + attr.width + ((width / 2 + 5) * (display === outside ? 1 : -1))) :
48682                 (attr.x + ((width / 2 + 5) * (display === outside ? -1 : 1))));
48683             y = attr.y + groupBarWidth / 2;
48684         }
48685         
48686         finalAttr = {
48687             x: x,
48688             y: y
48689         };
48690         
48691         if (rotate) {
48692             finalAttr.rotate = {
48693                 x: x,
48694                 y: y,
48695                 degrees: 270
48696             };
48697         }
48698         
48699         if (animate && resizing) {
48700             if (column) {
48701                 x = attr.x + attr.width / 2;
48702                 y = zero;
48703             } else {
48704                 x = zero;
48705                 y = attr.y + attr.height / 2;
48706             }
48707             label.setAttributes({
48708                 x: x,
48709                 y: y
48710             }, true);
48711             if (rotate) {
48712                 label.setAttributes({
48713                     rotate: {
48714                         x: x,
48715                         y: y,
48716                         degrees: 270
48717                     }
48718                 }, true);
48719             }
48720         }
48721         
48722         if (animate) {
48723             me.onAnimate(label, { to: finalAttr });
48724         }
48725         else {
48726             label.setAttributes(Ext.apply(finalAttr, {
48727                 hidden: false
48728             }), true);
48729         }
48730     },
48731
48732     
48733     getLabelSize: function(value) {
48734         var tester = this.testerLabel,
48735             config = this.label,
48736             endLabelStyle = Ext.apply({}, config, this.seriesLabelStyle || {}),
48737             rotated = config.orientation === 'vertical',
48738             bbox, w, h,
48739             undef;
48740         if (!tester) {
48741             tester = this.testerLabel = this.chart.surface.add(Ext.apply({
48742                 type: 'text',
48743                 opacity: 0
48744             }, endLabelStyle));
48745         }
48746         tester.setAttributes({
48747             text: value
48748         }, true);
48749
48750         
48751         bbox = tester.getBBox();
48752         w = bbox.width;
48753         h = bbox.height;
48754         return {
48755             width: rotated ? h : w,
48756             height: rotated ? w : h
48757         };
48758     },
48759
48760     
48761     onAnimate: function(sprite, attr) {
48762         sprite.show();
48763         return this.callParent(arguments);
48764     },
48765
48766     isItemInPoint: function(x, y, item) {
48767         var bbox = item.sprite.getBBox();
48768         return bbox.x <= x && bbox.y <= y
48769             && (bbox.x + bbox.width) >= x
48770             && (bbox.y + bbox.height) >= y;
48771     },
48772
48773     
48774     hideAll: function() {
48775         var axes = this.chart.axes;
48776         if (!isNaN(this._index)) {
48777             if (!this.__excludes) {
48778                 this.__excludes = [];
48779             }
48780             this.__excludes[this._index] = true;
48781             this.drawSeries();
48782             axes.each(function(axis) {
48783                 axis.drawAxis();
48784             });
48785         }
48786     },
48787
48788     
48789     showAll: function() {
48790         var axes = this.chart.axes;
48791         if (!isNaN(this._index)) {
48792             if (!this.__excludes) {
48793                 this.__excludes = [];
48794             }
48795             this.__excludes[this._index] = false;
48796             this.drawSeries();
48797             axes.each(function(axis) {
48798                 axis.drawAxis();
48799             });
48800         }
48801     },
48802
48803     
48804     getLegendColor: function(index) {
48805         var me = this,
48806             colorLength = me.colorArrayStyle.length;
48807
48808         if (me.style && me.style.fill) {
48809             return me.style.fill;
48810         } else {
48811             return me.colorArrayStyle[index % colorLength];
48812         }
48813     },
48814
48815     highlightItem: function(item) {
48816         this.callParent(arguments);
48817         this.renderLabels();
48818     },
48819
48820     unHighlightItem: function() {
48821         this.callParent(arguments);
48822         this.renderLabels();
48823     },
48824
48825     cleanHighlights: function() {
48826         this.callParent(arguments);
48827         this.renderLabels();
48828     }
48829 });
48830
48831 Ext.define('Ext.chart.series.Column', {
48832
48833     
48834
48835     alternateClassName: ['Ext.chart.ColumnSeries', 'Ext.chart.ColumnChart', 'Ext.chart.StackedColumnChart'],
48836
48837     extend: 'Ext.chart.series.Bar',
48838
48839     
48840
48841     type: 'column',
48842     alias: 'series.column',
48843
48844     column: true,
48845
48846     
48847     xPadding: 10,
48848
48849     
48850     yPadding: 0
48851 });
48852
48853 Ext.define('Ext.chart.series.Gauge', {
48854
48855     
48856
48857     extend: 'Ext.chart.series.Series',
48858
48859     
48860
48861     type: "gauge",
48862     alias: 'series.gauge',
48863
48864     rad: Math.PI / 180,
48865
48866     
48867     highlightDuration: 150,
48868
48869     
48870     angleField: false,
48871
48872     
48873     needle: false,
48874     
48875     
48876     donut: false,
48877
48878     
48879     showInLegend: false,
48880
48881     
48882     style: {},
48883     
48884     constructor: function(config) {
48885         this.callParent(arguments);
48886         var me = this,
48887             chart = me.chart,
48888             surface = chart.surface,
48889             store = chart.store,
48890             shadow = chart.shadow, i, l, cfg;
48891         Ext.apply(me, config, {
48892             shadowAttributes: [{
48893                 "stroke-width": 6,
48894                 "stroke-opacity": 1,
48895                 stroke: 'rgb(200, 200, 200)',
48896                 translate: {
48897                     x: 1.2,
48898                     y: 2
48899                 }
48900             },
48901             {
48902                 "stroke-width": 4,
48903                 "stroke-opacity": 1,
48904                 stroke: 'rgb(150, 150, 150)',
48905                 translate: {
48906                     x: 0.9,
48907                     y: 1.5
48908                 }
48909             },
48910             {
48911                 "stroke-width": 2,
48912                 "stroke-opacity": 1,
48913                 stroke: 'rgb(100, 100, 100)',
48914                 translate: {
48915                     x: 0.6,
48916                     y: 1
48917                 }
48918             }]
48919         });
48920         me.group = surface.getGroup(me.seriesId);
48921         if (shadow) {
48922             for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
48923                 me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
48924             }
48925         }
48926         surface.customAttributes.segment = function(opt) {
48927             return me.getSegment(opt);
48928         };
48929     },
48930     
48931     //@private updates some onbefore render parameters.
48932
48933     initialize: function() {
48934         var me = this,
48935             store = me.chart.getChartStore();
48936         
48937         me.yField = [];
48938         if (me.label.field) {
48939             store.each(function(rec) {
48940                 me.yField.push(rec.get(me.label.field));
48941             });
48942         }
48943     },
48944
48945     
48946     getSegment: function(opt) {
48947         var me = this,
48948             rad = me.rad,
48949             cos = Math.cos,
48950             sin = Math.sin,
48951             abs = Math.abs,
48952             x = me.centerX,
48953             y = me.centerY,
48954             x1 = 0, x2 = 0, x3 = 0, x4 = 0,
48955             y1 = 0, y2 = 0, y3 = 0, y4 = 0,
48956             delta = 1e-2,
48957             r = opt.endRho - opt.startRho,
48958             startAngle = opt.startAngle,
48959             endAngle = opt.endAngle,
48960             midAngle = (startAngle + endAngle) / 2 * rad,
48961             margin = opt.margin || 0,
48962             flag = abs(endAngle - startAngle) > 180,
48963             a1 = Math.min(startAngle, endAngle) * rad,
48964             a2 = Math.max(startAngle, endAngle) * rad,
48965             singleSlice = false;
48966
48967         x += margin * cos(midAngle);
48968         y += margin * sin(midAngle);
48969
48970         x1 = x + opt.startRho * cos(a1);
48971         y1 = y + opt.startRho * sin(a1);
48972
48973         x2 = x + opt.endRho * cos(a1);
48974         y2 = y + opt.endRho * sin(a1);
48975
48976         x3 = x + opt.startRho * cos(a2);
48977         y3 = y + opt.startRho * sin(a2);
48978
48979         x4 = x + opt.endRho * cos(a2);
48980         y4 = y + opt.endRho * sin(a2);
48981
48982         if (abs(x1 - x3) <= delta && abs(y1 - y3) <= delta) {
48983             singleSlice = true;
48984         }
48985         
48986         if (singleSlice) {
48987             return {
48988                 path: [
48989                 ["M", x1, y1],
48990                 ["L", x2, y2],
48991                 ["A", opt.endRho, opt.endRho, 0, +flag, 1, x4, y4],
48992                 ["Z"]]
48993             };
48994         } else {
48995             return {
48996                 path: [
48997                 ["M", x1, y1],
48998                 ["L", x2, y2],
48999                 ["A", opt.endRho, opt.endRho, 0, +flag, 1, x4, y4],
49000                 ["L", x3, y3],
49001                 ["A", opt.startRho, opt.startRho, 0, +flag, 0, x1, y1],
49002                 ["Z"]]
49003             };
49004         }
49005     },
49006
49007     
49008     calcMiddle: function(item) {
49009         var me = this,
49010             rad = me.rad,
49011             slice = item.slice,
49012             x = me.centerX,
49013             y = me.centerY,
49014             startAngle = slice.startAngle,
49015             endAngle = slice.endAngle,
49016             radius = Math.max(('rho' in slice) ? slice.rho: me.radius, me.label.minMargin),
49017             donut = +me.donut,
49018             a1 = Math.min(startAngle, endAngle) * rad,
49019             a2 = Math.max(startAngle, endAngle) * rad,
49020             midAngle = -(a1 + (a2 - a1) / 2),
49021             xm = x + (item.endRho + item.startRho) / 2 * Math.cos(midAngle),
49022             ym = y - (item.endRho + item.startRho) / 2 * Math.sin(midAngle);
49023
49024         item.middle = {
49025             x: xm,
49026             y: ym
49027         };
49028     },
49029
49030     
49031     drawSeries: function() {
49032         var me = this,
49033             chart = me.chart,
49034             store = chart.getChartStore(),
49035             group = me.group,
49036             animate = me.chart.animate,
49037             axis = me.chart.axes.get(0),
49038             minimum = axis && axis.minimum || me.minimum || 0,
49039             maximum = axis && axis.maximum || me.maximum || 0,
49040             field = me.angleField || me.field || me.xField,
49041             surface = chart.surface,
49042             chartBBox = chart.chartBBox,
49043             rad = me.rad,
49044             donut = +me.donut,
49045             values = {},
49046             items = [],
49047             seriesStyle = me.seriesStyle,
49048             seriesLabelStyle = me.seriesLabelStyle,
49049             colorArrayStyle = me.colorArrayStyle,
49050             colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
49051             gutterX = chart.maxGutter[0],
49052             gutterY = chart.maxGutter[1],
49053             cos = Math.cos,
49054             sin = Math.sin,
49055             rendererAttributes, centerX, centerY, slice, slices, sprite, value,
49056             item, ln, record, i, j, startAngle, endAngle, middleAngle, sliceLength, path,
49057             p, spriteOptions, bbox, splitAngle, sliceA, sliceB;
49058         
49059         Ext.apply(seriesStyle, me.style || {});
49060
49061         me.setBBox();
49062         bbox = me.bbox;
49063
49064         
49065         if (me.colorSet) {
49066             colorArrayStyle = me.colorSet;
49067             colorArrayLength = colorArrayStyle.length;
49068         }
49069         
49070         
49071         if (!store || !store.getCount()) {
49072             return;
49073         }
49074         
49075         centerX = me.centerX = chartBBox.x + (chartBBox.width / 2);
49076         centerY = me.centerY = chartBBox.y + chartBBox.height;
49077         me.radius = Math.min(centerX - chartBBox.x, centerY - chartBBox.y);
49078         me.slices = slices = [];
49079         me.items = items = [];
49080         
49081         if (!me.value) {
49082             record = store.getAt(0);
49083             me.value = record.get(field);
49084         }
49085         
49086         value = me.value;
49087         if (me.needle) {
49088             sliceA = {
49089                 series: me,
49090                 value: value,
49091                 startAngle: -180,
49092                 endAngle: 0,
49093                 rho: me.radius
49094             };
49095             splitAngle = -180 * (1 - (value - minimum) / (maximum - minimum));
49096             slices.push(sliceA);
49097         } else {
49098             splitAngle = -180 * (1 - (value - minimum) / (maximum - minimum));
49099             sliceA = {
49100                 series: me,
49101                 value: value,
49102                 startAngle: -180,
49103                 endAngle: splitAngle,
49104                 rho: me.radius
49105             };
49106             sliceB = {
49107                 series: me,
49108                 value: me.maximum - value,
49109                 startAngle: splitAngle,
49110                 endAngle: 0,
49111                 rho: me.radius
49112             };
49113             slices.push(sliceA, sliceB);
49114         }
49115         
49116         
49117         for (i = 0, ln = slices.length; i < ln; i++) {
49118             slice = slices[i];
49119             sprite = group.getAt(i);
49120             
49121             rendererAttributes = Ext.apply({
49122                 segment: {
49123                     startAngle: slice.startAngle,
49124                     endAngle: slice.endAngle,
49125                     margin: 0,
49126                     rho: slice.rho,
49127                     startRho: slice.rho * +donut / 100,
49128                     endRho: slice.rho
49129                 } 
49130             }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[i % colorArrayLength] } || {}));
49131
49132             item = Ext.apply({},
49133             rendererAttributes.segment, {
49134                 slice: slice,
49135                 series: me,
49136                 storeItem: record,
49137                 index: i
49138             });
49139             items[i] = item;
49140             
49141             if (!sprite) {
49142                 spriteOptions = Ext.apply({
49143                     type: "path",
49144                     group: group
49145                 }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[i % colorArrayLength] } || {}));
49146                 sprite = surface.add(Ext.apply(spriteOptions, rendererAttributes));
49147             }
49148             slice.sprite = slice.sprite || [];
49149             item.sprite = sprite;
49150             slice.sprite.push(sprite);
49151             if (animate) {
49152                 rendererAttributes = me.renderer(sprite, record, rendererAttributes, i, store);
49153                 sprite._to = rendererAttributes;
49154                 me.onAnimate(sprite, {
49155                     to: rendererAttributes
49156                 });
49157             } else {
49158                 rendererAttributes = me.renderer(sprite, record, Ext.apply(rendererAttributes, {
49159                     hidden: false
49160                 }), i, store);
49161                 sprite.setAttributes(rendererAttributes, true);
49162             }
49163         }
49164         
49165         if (me.needle) {
49166             splitAngle = splitAngle * Math.PI / 180;
49167             
49168             if (!me.needleSprite) {
49169                 me.needleSprite = me.chart.surface.add({
49170                     type: 'path',
49171                     path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
49172                                 centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
49173                            'L', centerX + me.radius * cos(splitAngle),
49174                                 centerY + -Math.abs(me.radius * sin(splitAngle))],
49175                     'stroke-width': 4,
49176                     'stroke': '#222'
49177                 });
49178             } else {
49179                 if (animate) {
49180                     me.onAnimate(me.needleSprite, {
49181                         to: {
49182                         path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
49183                                     centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
49184                                'L', centerX + me.radius * cos(splitAngle),
49185                                     centerY + -Math.abs(me.radius * sin(splitAngle))]
49186                         }
49187                     });
49188                 } else {
49189                     me.needleSprite.setAttributes({
49190                         type: 'path',
49191                         path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
49192                                     centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
49193                                'L', centerX + me.radius * cos(splitAngle),
49194                                     centerY + -Math.abs(me.radius * sin(splitAngle))]
49195                     });
49196                 }
49197             }
49198             me.needleSprite.setAttributes({
49199                 hidden: false    
49200             }, true);
49201         }
49202         
49203         delete me.value;
49204     },
49205     
49206     
49207     setValue: function (value) {
49208         this.value = value;
49209         this.drawSeries();
49210     },
49211
49212     
49213     onCreateLabel: function(storeItem, item, i, display) {},
49214
49215     
49216     onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {},
49217
49218     
49219     onPlaceCallout: function() {},
49220
49221     
49222     onAnimate: function(sprite, attr) {
49223         sprite.show();
49224         return this.callParent(arguments);
49225     },
49226
49227     isItemInPoint: function(x, y, item, i) {
49228         return false;
49229     },
49230     
49231     
49232     showAll: function() {
49233         if (!isNaN(this._index)) {
49234             this.__excludes[this._index] = false;
49235             this.drawSeries();
49236         }
49237     },
49238     
49239     
49240     getLegendColor: function(index) {
49241         var me = this;
49242         return me.colorArrayStyle[index % me.colorArrayStyle.length];
49243     }
49244 });
49245
49246
49247
49248 Ext.define('Ext.chart.series.Line', {
49249
49250     
49251
49252     extend: 'Ext.chart.series.Cartesian',
49253
49254     alternateClassName: ['Ext.chart.LineSeries', 'Ext.chart.LineChart'],
49255
49256     requires: ['Ext.chart.axis.Axis', 'Ext.chart.Shape', 'Ext.draw.Draw', 'Ext.fx.Anim'],
49257
49258     
49259
49260     type: 'line',
49261
49262     alias: 'series.line',
49263
49264     
49265
49266     
49267     selectionTolerance: 20,
49268
49269     
49270     showMarkers: true,
49271
49272     
49273     markerConfig: {},
49274
49275     
49276     style: {},
49277
49278     
49279     smooth: false,
49280
49281     
49282     defaultSmoothness: 3,
49283
49284     
49285     fill: false,
49286
49287     constructor: function(config) {
49288         this.callParent(arguments);
49289         var me = this,
49290             surface = me.chart.surface,
49291             shadow = me.chart.shadow,
49292             i, l;
49293         Ext.apply(me, config, {
49294             highlightCfg: {
49295                 'stroke-width': 3
49296             },
49297             shadowAttributes: [{
49298                 "stroke-width": 6,
49299                 "stroke-opacity": 0.05,
49300                 stroke: 'rgb(0, 0, 0)',
49301                 translate: {
49302                     x: 1,
49303                     y: 1
49304                 }
49305             }, {
49306                 "stroke-width": 4,
49307                 "stroke-opacity": 0.1,
49308                 stroke: 'rgb(0, 0, 0)',
49309                 translate: {
49310                     x: 1,
49311                     y: 1
49312                 }
49313             }, {
49314                 "stroke-width": 2,
49315                 "stroke-opacity": 0.15,
49316                 stroke: 'rgb(0, 0, 0)',
49317                 translate: {
49318                     x: 1,
49319                     y: 1
49320                 }
49321             }]
49322         });
49323         me.group = surface.getGroup(me.seriesId);
49324         if (me.showMarkers) {
49325             me.markerGroup = surface.getGroup(me.seriesId + '-markers');
49326         }
49327         if (shadow) {
49328             for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
49329                 me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
49330             }
49331         }
49332     },
49333
49334     
49335     shrink: function(xValues, yValues, size) {
49336         
49337         var len = xValues.length,
49338             ratio = Math.floor(len / size),
49339             i = 1,
49340             xSum = 0,
49341             ySum = 0,
49342             xRes = [xValues[0]],
49343             yRes = [yValues[0]];
49344
49345         for (; i < len; ++i) {
49346             xSum += xValues[i] || 0;
49347             ySum += yValues[i] || 0;
49348             if (i % ratio == 0) {
49349                 xRes.push(xSum/ratio);
49350                 yRes.push(ySum/ratio);
49351                 xSum = 0;
49352                 ySum = 0;
49353             }
49354         }
49355         return {
49356             x: xRes,
49357             y: yRes
49358         };
49359     },
49360
49361     
49362     drawSeries: function() {
49363         var me = this,
49364             chart = me.chart,
49365             chartAxes = chart.axes,
49366             store = chart.getChartStore(),
49367             storeCount = store.getCount(),
49368             surface = me.chart.surface,
49369             bbox = {},
49370             group = me.group,
49371             showMarkers = me.showMarkers,
49372             markerGroup = me.markerGroup,
49373             enableShadows = chart.shadow,
49374             shadowGroups = me.shadowGroups,
49375             shadowAttributes = me.shadowAttributes,
49376             smooth = me.smooth,
49377             lnsh = shadowGroups.length,
49378             dummyPath = ["M"],
49379             path = ["M"],
49380             renderPath = ["M"],
49381             smoothPath = ["M"],
49382             markerIndex = chart.markerIndex,
49383             axes = [].concat(me.axis),
49384             shadowBarAttr,
49385             xValues = [],
49386             xValueMap = {},
49387             yValues = [],
49388             yValueMap = {},
49389             onbreak = false,
49390             storeIndices = [],
49391             markerStyle = me.markerStyle,
49392             seriesStyle = me.style,
49393             colorArrayStyle = me.colorArrayStyle,
49394             colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
49395             isNumber = Ext.isNumber,
49396             seriesIdx = me.seriesIdx, 
49397             boundAxes = me.getAxesForXAndYFields(),
49398             boundXAxis = boundAxes.xAxis,
49399             boundYAxis = boundAxes.yAxis,
49400             shadows, shadow, shindex, fromPath, fill, fillPath, rendererAttributes,
49401             x, y, prevX, prevY, firstX, firstY, markerCount, i, j, ln, axis, ends, marker, markerAux, item, xValue,
49402             yValue, coords, xScale, yScale, minX, maxX, minY, maxY, line, animation, endMarkerStyle,
49403             endLineStyle, type, count, items;
49404
49405         if (me.fireEvent('beforedraw', me) === false) {
49406             return;
49407         }
49408
49409         
49410         if (!storeCount || me.seriesIsHidden) {
49411             items = this.items;
49412             if (items) {
49413                 for (i = 0, ln = items.length; i < ln; ++i) {
49414                     if (items[i].sprite) {
49415                         items[i].sprite.hide(true);
49416                     }
49417                 }
49418             }
49419             return;
49420         }
49421
49422         
49423         endMarkerStyle = Ext.apply(markerStyle || {}, me.markerConfig);
49424         type = endMarkerStyle.type;
49425         delete endMarkerStyle.type;
49426         endLineStyle = seriesStyle;
49427         
49428         
49429         if (!endLineStyle['stroke-width']) {
49430             endLineStyle['stroke-width'] = 0.5;
49431         }
49432         
49433         
49434         if (markerIndex && markerGroup && markerGroup.getCount()) {
49435             for (i = 0; i < markerIndex; i++) {
49436                 marker = markerGroup.getAt(i);
49437                 markerGroup.remove(marker);
49438                 markerGroup.add(marker);
49439                 markerAux = markerGroup.getAt(markerGroup.getCount() - 2);
49440                 marker.setAttributes({
49441                     x: 0,
49442                     y: 0,
49443                     translate: {
49444                         x: markerAux.attr.translation.x,
49445                         y: markerAux.attr.translation.y
49446                     }
49447                 }, true);
49448             }
49449         }
49450
49451         me.unHighlightItem();
49452         me.cleanHighlights();
49453
49454         me.setBBox();
49455         bbox = me.bbox;
49456         me.clipRect = [bbox.x, bbox.y, bbox.width, bbox.height];
49457         for (i = 0, ln = axes.length; i < ln; i++) {
49458             axis = chartAxes.get(axes[i]);
49459             if (axis) {
49460                 ends = axis.calcEnds();
49461                 if (axis.position == 'top' || axis.position == 'bottom') {
49462                     minX = ends.from;
49463                     maxX = ends.to;
49464                 }
49465                 else {
49466                     minY = ends.from;
49467                     maxY = ends.to;
49468                 }
49469             }
49470         }
49471         
49472         
49473         
49474         if (me.xField && !isNumber(minX) &&
49475             (boundXAxis == 'bottom' || boundXAxis == 'top') && 
49476             !chartAxes.get(boundXAxis)) {
49477             axis = Ext.create('Ext.chart.axis.Axis', {
49478                 chart: chart,
49479                 fields: [].concat(me.xField)
49480             }).calcEnds();
49481             minX = axis.from;
49482             maxX = axis.to;
49483         }
49484         if (me.yField && !isNumber(minY) &&
49485             (boundYAxis == 'right' || boundYAxis == 'left') &&
49486             !chartAxes.get(boundYAxis)) {
49487             axis = Ext.create('Ext.chart.axis.Axis', {
49488                 chart: chart,
49489                 fields: [].concat(me.yField)
49490             }).calcEnds();
49491             minY = axis.from;
49492             maxY = axis.to;
49493         }
49494         if (isNaN(minX)) {
49495             minX = 0;
49496             xScale = bbox.width / ((storeCount - 1) || 1);
49497         }
49498         else {
49499             xScale = bbox.width / ((maxX - minX) || (storeCount -1) || 1);
49500         }
49501
49502         if (isNaN(minY)) {
49503             minY = 0;
49504             yScale = bbox.height / ((storeCount - 1) || 1);
49505         }
49506         else {
49507             yScale = bbox.height / ((maxY - minY) || (storeCount - 1) || 1);
49508         }
49509
49510         
49511         me.eachRecord(function(record, i) {
49512             xValue = record.get(me.xField);
49513
49514             
49515             if (typeof xValue == 'string' || typeof xValue == 'object' && !Ext.isDate(xValue)
49516                 
49517                 || boundXAxis && chartAxes.get(boundXAxis) && chartAxes.get(boundXAxis).type == 'Category') {
49518                     if (xValue in xValueMap) {
49519                         xValue = xValueMap[xValue];
49520                     } else {
49521                         xValue = xValueMap[xValue] = i;
49522                     }
49523             }
49524
49525             
49526             yValue = record.get(me.yField);
49527             
49528             if (typeof yValue == 'undefined' || (typeof yValue == 'string' && !yValue)) {
49529                 return;
49530             }
49531             
49532             if (typeof yValue == 'string' || typeof yValue == 'object' && !Ext.isDate(yValue)
49533                 
49534                 || boundYAxis && chartAxes.get(boundYAxis) && chartAxes.get(boundYAxis).type == 'Category') {
49535                 yValue = i;
49536             }
49537             storeIndices.push(i);
49538             xValues.push(xValue);
49539             yValues.push(yValue);
49540         });
49541
49542         ln = xValues.length;
49543         if (ln > bbox.width) {
49544             coords = me.shrink(xValues, yValues, bbox.width);
49545             xValues = coords.x;
49546             yValues = coords.y;
49547         }
49548
49549         me.items = [];
49550
49551         count = 0;
49552         ln = xValues.length;
49553         for (i = 0; i < ln; i++) {
49554             xValue = xValues[i];
49555             yValue = yValues[i];
49556             if (yValue === false) {
49557                 if (path.length == 1) {
49558                     path = [];
49559                 }
49560                 onbreak = true;
49561                 me.items.push(false);
49562                 continue;
49563             } else {
49564                 x = (bbox.x + (xValue - minX) * xScale).toFixed(2);
49565                 y = ((bbox.y + bbox.height) - (yValue - minY) * yScale).toFixed(2);
49566                 if (onbreak) {
49567                     onbreak = false;
49568                     path.push('M');
49569                 }
49570                 path = path.concat([x, y]);
49571             }
49572             if ((typeof firstY == 'undefined') && (typeof y != 'undefined')) {
49573                 firstY = y;
49574                 firstX = x;
49575             }
49576             
49577             if (!me.line || chart.resizing) {
49578                 dummyPath = dummyPath.concat([x, bbox.y + bbox.height / 2]);
49579             }
49580
49581             
49582             if (chart.animate && chart.resizing && me.line) {
49583                 me.line.setAttributes({
49584                     path: dummyPath
49585                 }, true);
49586                 if (me.fillPath) {
49587                     me.fillPath.setAttributes({
49588                         path: dummyPath,
49589                         opacity: 0.2
49590                     }, true);
49591                 }
49592                 if (me.line.shadows) {
49593                     shadows = me.line.shadows;
49594                     for (j = 0, lnsh = shadows.length; j < lnsh; j++) {
49595                         shadow = shadows[j];
49596                         shadow.setAttributes({
49597                             path: dummyPath
49598                         }, true);
49599                     }
49600                 }
49601             }
49602             if (showMarkers) {
49603                 marker = markerGroup.getAt(count++);
49604                 if (!marker) {
49605                     marker = Ext.chart.Shape[type](surface, Ext.apply({
49606                         group: [group, markerGroup],
49607                         x: 0, y: 0,
49608                         translate: {
49609                             x: +(prevX || x),
49610                             y: prevY || (bbox.y + bbox.height / 2)
49611                         },
49612                         value: '"' + xValue + ', ' + yValue + '"',
49613                         zIndex: 4000
49614                     }, endMarkerStyle));
49615                     marker._to = {
49616                         translate: {
49617                             x: +x,
49618                             y: +y
49619                         }
49620                     };
49621                 } else {
49622                     marker.setAttributes({
49623                         value: '"' + xValue + ', ' + yValue + '"',
49624                         x: 0, y: 0,
49625                         hidden: false
49626                     }, true);
49627                     marker._to = {
49628                         translate: {
49629                             x: +x, 
49630                             y: +y
49631                         }
49632                     };
49633                 }
49634             }
49635             me.items.push({
49636                 series: me,
49637                 value: [xValue, yValue],
49638                 point: [x, y],
49639                 sprite: marker,
49640                 storeItem: store.getAt(storeIndices[i])
49641             });
49642             prevX = x;
49643             prevY = y;
49644         }
49645
49646         if (path.length <= 1) {
49647             
49648             return;
49649         }
49650
49651         if (me.smooth) {
49652             smoothPath = Ext.draw.Draw.smooth(path, isNumber(smooth) ? smooth : me.defaultSmoothness);
49653         }
49654
49655         renderPath = smooth ? smoothPath : path;
49656
49657         
49658         if (chart.markerIndex && me.previousPath) {
49659             fromPath = me.previousPath;
49660             if (!smooth) {
49661                 Ext.Array.erase(fromPath, 1, 2);
49662             }
49663         } else {
49664             fromPath = path;
49665         }
49666
49667         
49668         if (!me.line) {
49669             me.line = surface.add(Ext.apply({
49670                 type: 'path',
49671                 group: group,
49672                 path: dummyPath,
49673                 stroke: endLineStyle.stroke || endLineStyle.fill
49674             }, endLineStyle || {}));
49675
49676             if (enableShadows) {
49677                 me.line.setAttributes(Ext.apply({}, me.shadowOptions), true);
49678             }
49679
49680             
49681             me.line.setAttributes({
49682                 fill: 'none',
49683                 zIndex: 3000
49684             });
49685             if (!endLineStyle.stroke && colorArrayLength) {
49686                 me.line.setAttributes({
49687                     stroke: colorArrayStyle[seriesIdx % colorArrayLength]
49688                 }, true);
49689             }
49690             if (enableShadows) {
49691                 
49692                 shadows = me.line.shadows = [];
49693                 for (shindex = 0; shindex < lnsh; shindex++) {
49694                     shadowBarAttr = shadowAttributes[shindex];
49695                     shadowBarAttr = Ext.apply({}, shadowBarAttr, { path: dummyPath });
49696                     shadow = surface.add(Ext.apply({}, {
49697                         type: 'path',
49698                         group: shadowGroups[shindex]
49699                     }, shadowBarAttr));
49700                     shadows.push(shadow);
49701                 }
49702             }
49703         }
49704         if (me.fill) {
49705             fillPath = renderPath.concat([
49706                 ["L", x, bbox.y + bbox.height],
49707                 ["L", firstX, bbox.y + bbox.height],
49708                 ["L", firstX, firstY]
49709             ]);
49710             if (!me.fillPath) {
49711                 me.fillPath = surface.add({
49712                     group: group,
49713                     type: 'path',
49714                     opacity: endLineStyle.opacity || 0.3,
49715                     fill: endLineStyle.fill || colorArrayStyle[seriesIdx % colorArrayLength],
49716                     path: dummyPath
49717                 });
49718             }
49719         }
49720         markerCount = showMarkers && markerGroup.getCount();
49721         if (chart.animate) {
49722             fill = me.fill;
49723             line = me.line;
49724             
49725             rendererAttributes = me.renderer(line, false, { path: renderPath }, i, store);
49726             Ext.apply(rendererAttributes, endLineStyle || {}, {
49727                 stroke: endLineStyle.stroke || endLineStyle.fill
49728             });
49729             
49730             delete rendererAttributes.fill;
49731             line.show(true);
49732             if (chart.markerIndex && me.previousPath) {
49733                 me.animation = animation = me.onAnimate(line, {
49734                     to: rendererAttributes,
49735                     from: {
49736                         path: fromPath
49737                     }
49738                 });
49739             } else {
49740                 me.animation = animation = me.onAnimate(line, {
49741                     to: rendererAttributes
49742                 });
49743             }
49744             
49745             if (enableShadows) {
49746                 shadows = line.shadows;
49747                 for(j = 0; j < lnsh; j++) {
49748                     shadows[j].show(true);
49749                     if (chart.markerIndex && me.previousPath) {
49750                         me.onAnimate(shadows[j], {
49751                             to: { path: renderPath },
49752                             from: { path: fromPath }
49753                         });
49754                     } else {
49755                         me.onAnimate(shadows[j], {
49756                             to: { path: renderPath }
49757                         });
49758                     }
49759                 }
49760             }
49761             
49762             if (fill) {
49763                 me.fillPath.show(true);
49764                 me.onAnimate(me.fillPath, {
49765                     to: Ext.apply({}, {
49766                         path: fillPath,
49767                         fill: endLineStyle.fill || colorArrayStyle[seriesIdx % colorArrayLength],
49768                         'stroke-width': 0
49769                     }, endLineStyle || {})
49770                 });
49771             }
49772             
49773             if (showMarkers) {
49774                 count = 0;
49775                 for(i = 0; i < ln; i++) {
49776                     if (me.items[i]) {
49777                         item = markerGroup.getAt(count++);
49778                         if (item) {
49779                             rendererAttributes = me.renderer(item, store.getAt(i), item._to, i, store);
49780                             me.onAnimate(item, {
49781                                 to: Ext.apply(rendererAttributes, endMarkerStyle || {})
49782                             });
49783                             item.show(true);
49784                         }
49785                     }
49786                 }
49787                 for(; count < markerCount; count++) {
49788                     item = markerGroup.getAt(count);
49789                     item.hide(true);
49790                 }
49791
49792
49793
49794
49795             }
49796         } else {
49797             rendererAttributes = me.renderer(me.line, false, { path: renderPath, hidden: false }, i, store);
49798             Ext.apply(rendererAttributes, endLineStyle || {}, {
49799                 stroke: endLineStyle.stroke || endLineStyle.fill
49800             });
49801             
49802             delete rendererAttributes.fill;
49803             me.line.setAttributes(rendererAttributes, true);
49804             
49805             if (enableShadows) {
49806                 shadows = me.line.shadows;
49807                 for(j = 0; j < lnsh; j++) {
49808                     shadows[j].setAttributes({
49809                         path: renderPath,
49810                         hidden: false
49811                     }, true);
49812                 }
49813             }
49814             if (me.fill) {
49815                 me.fillPath.setAttributes({
49816                     path: fillPath,
49817                     hidden: false
49818                 }, true);
49819             }
49820             if (showMarkers) {
49821                 count = 0;
49822                 for(i = 0; i < ln; i++) {
49823                     if (me.items[i]) {
49824                         item = markerGroup.getAt(count++);
49825                         if (item) {
49826                             rendererAttributes = me.renderer(item, store.getAt(i), item._to, i, store);
49827                             item.setAttributes(Ext.apply(endMarkerStyle || {}, rendererAttributes || {}), true);
49828                             item.show(true);
49829                         }
49830                     }
49831                 }
49832                 for(; count < markerCount; count++) {
49833                     item = markerGroup.getAt(count);
49834                     item.hide(true);
49835                 }
49836             }
49837         }
49838
49839         if (chart.markerIndex) {
49840             if (me.smooth) {
49841                 Ext.Array.erase(path, 1, 2);
49842             } else {
49843                 Ext.Array.splice(path, 1, 0, path[1], path[2]);
49844             }
49845             me.previousPath = path;
49846         }
49847         me.renderLabels();
49848         me.renderCallouts();
49849
49850         me.fireEvent('draw', me);
49851     },
49852
49853     
49854     onCreateLabel: function(storeItem, item, i, display) {
49855         var me = this,
49856             group = me.labelsGroup,
49857             config = me.label,
49858             bbox = me.bbox,
49859             endLabelStyle = Ext.apply(config, me.seriesLabelStyle);
49860
49861         return me.chart.surface.add(Ext.apply({
49862             'type': 'text',
49863             'text-anchor': 'middle',
49864             'group': group,
49865             'x': item.point[0],
49866             'y': bbox.y + bbox.height / 2
49867         }, endLabelStyle || {}));
49868     },
49869
49870     
49871     onPlaceLabel: function(label, storeItem, item, i, display, animate) {
49872         var me = this,
49873             chart = me.chart,
49874             resizing = chart.resizing,
49875             config = me.label,
49876             format = config.renderer,
49877             field = config.field,
49878             bbox = me.bbox,
49879             x = item.point[0],
49880             y = item.point[1],
49881             radius = item.sprite.attr.radius,
49882             bb, width, height;
49883
49884         label.setAttributes({
49885             text: format(storeItem.get(field)),
49886             hidden: true
49887         }, true);
49888
49889         if (display == 'rotate') {
49890             label.setAttributes({
49891                 'text-anchor': 'start',
49892                 'rotation': {
49893                     x: x,
49894                     y: y,
49895                     degrees: -45
49896                 }
49897             }, true);
49898             
49899             bb = label.getBBox();
49900             width = bb.width;
49901             height = bb.height;
49902             x = x < bbox.x? bbox.x : x;
49903             x = (x + width > bbox.x + bbox.width)? (x - (x + width - bbox.x - bbox.width)) : x;
49904             y = (y - height < bbox.y)? bbox.y + height : y;
49905
49906         } else if (display == 'under' || display == 'over') {
49907             
49908             bb = item.sprite.getBBox();
49909             bb.width = bb.width || (radius * 2);
49910             bb.height = bb.height || (radius * 2);
49911             y = y + (display == 'over'? -bb.height : bb.height);
49912             
49913             bb = label.getBBox();
49914             width = bb.width/2;
49915             height = bb.height/2;
49916             x = x - width < bbox.x? bbox.x + width : x;
49917             x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
49918             y = y - height < bbox.y? bbox.y + height : y;
49919             y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
49920         }
49921
49922         if (me.chart.animate && !me.chart.resizing) {
49923             label.show(true);
49924             me.onAnimate(label, {
49925                 to: {
49926                     x: x,
49927                     y: y
49928                 }
49929             });
49930         } else {
49931             label.setAttributes({
49932                 x: x,
49933                 y: y
49934             }, true);
49935             if (resizing && me.animation) {
49936                 me.animation.on('afteranimate', function() {
49937                     label.show(true);
49938                 });
49939             } else {
49940                 label.show(true);
49941             }
49942         }
49943     },
49944
49945     //@private Overriding highlights.js highlightItem method.
49946
49947     highlightItem: function() {
49948         var me = this;
49949         me.callParent(arguments);
49950         if (me.line && !me.highlighted) {
49951             if (!('__strokeWidth' in me.line)) {
49952                 me.line.__strokeWidth = me.line.attr['stroke-width'] || 0;
49953             }
49954             if (me.line.__anim) {
49955                 me.line.__anim.paused = true;
49956             }
49957             me.line.__anim = Ext.create('Ext.fx.Anim', {
49958                 target: me.line,
49959                 to: {
49960                     'stroke-width': me.line.__strokeWidth + 3
49961                 }
49962             });
49963             me.highlighted = true;
49964         }
49965     },
49966
49967     //@private Overriding highlights.js unHighlightItem method.
49968
49969     unHighlightItem: function() {
49970         var me = this;
49971         me.callParent(arguments);
49972         if (me.line && me.highlighted) {
49973             me.line.__anim = Ext.create('Ext.fx.Anim', {
49974                 target: me.line,
49975                 to: {
49976                     'stroke-width': me.line.__strokeWidth
49977                 }
49978             });
49979             me.highlighted = false;
49980         }
49981     },
49982
49983     //@private called when a callout needs to be placed.
49984
49985     onPlaceCallout : function(callout, storeItem, item, i, display, animate, index) {
49986         if (!display) {
49987             return;
49988         }
49989
49990         var me = this,
49991             chart = me.chart,
49992             surface = chart.surface,
49993             resizing = chart.resizing,
49994             config = me.callouts,
49995             items = me.items,
49996             prev = i == 0? false : items[i -1].point,
49997             next = (i == items.length -1)? false : items[i +1].point,
49998             cur = [+item.point[0], +item.point[1]],
49999             dir, norm, normal, a, aprev, anext,
50000             offsetFromViz = config.offsetFromViz || 30,
50001             offsetToSide = config.offsetToSide || 10,
50002             offsetBox = config.offsetBox || 3,
50003             boxx, boxy, boxw, boxh,
50004             p, clipRect = me.clipRect,
50005             bbox = {
50006                 width: config.styles.width || 10,
50007                 height: config.styles.height || 10
50008             },
50009             x, y;
50010
50011         
50012         if (!prev) {
50013             prev = cur;
50014         }
50015         if (!next) {
50016             next = cur;
50017         }
50018         a = (next[1] - prev[1]) / (next[0] - prev[0]);
50019         aprev = (cur[1] - prev[1]) / (cur[0] - prev[0]);
50020         anext = (next[1] - cur[1]) / (next[0] - cur[0]);
50021
50022         norm = Math.sqrt(1 + a * a);
50023         dir = [1 / norm, a / norm];
50024         normal = [-dir[1], dir[0]];
50025
50026         
50027         if (aprev > 0 && anext < 0 && normal[1] < 0
50028             || aprev < 0 && anext > 0 && normal[1] > 0) {
50029             normal[0] *= -1;
50030             normal[1] *= -1;
50031         } else if (Math.abs(aprev) < Math.abs(anext) && normal[0] < 0
50032                    || Math.abs(aprev) > Math.abs(anext) && normal[0] > 0) {
50033             normal[0] *= -1;
50034             normal[1] *= -1;
50035         }
50036         
50037         x = cur[0] + normal[0] * offsetFromViz;
50038         y = cur[1] + normal[1] * offsetFromViz;
50039
50040         
50041         boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
50042         boxy = y - bbox.height /2 - offsetBox;
50043         boxw = bbox.width + 2 * offsetBox;
50044         boxh = bbox.height + 2 * offsetBox;
50045
50046         
50047         
50048         if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) {
50049             normal[0] *= -1;
50050         }
50051         if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) {
50052             normal[1] *= -1;
50053         }
50054
50055         
50056         x = cur[0] + normal[0] * offsetFromViz;
50057         y = cur[1] + normal[1] * offsetFromViz;
50058
50059         
50060         boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
50061         boxy = y - bbox.height /2 - offsetBox;
50062         boxw = bbox.width + 2 * offsetBox;
50063         boxh = bbox.height + 2 * offsetBox;
50064
50065         if (chart.animate) {
50066             
50067             me.onAnimate(callout.lines, {
50068                 to: {
50069                     path: ["M", cur[0], cur[1], "L", x, y, "Z"]
50070                 }
50071             });
50072             
50073             if (callout.panel) {
50074                 callout.panel.setPosition(boxx, boxy, true);
50075             }
50076         }
50077         else {
50078             
50079             callout.lines.setAttributes({
50080                 path: ["M", cur[0], cur[1], "L", x, y, "Z"]
50081             }, true);
50082             
50083             if (callout.panel) {
50084                 callout.panel.setPosition(boxx, boxy);
50085             }
50086         }
50087         for (p in callout) {
50088             callout[p].show(true);
50089         }
50090     },
50091
50092     isItemInPoint: function(x, y, item, i) {
50093         var me = this,
50094             items = me.items,
50095             tolerance = me.selectionTolerance,
50096             result = null,
50097             prevItem,
50098             nextItem,
50099             prevPoint,
50100             nextPoint,
50101             ln,
50102             x1,
50103             y1,
50104             x2,
50105             y2,
50106             xIntersect,
50107             yIntersect,
50108             dist1, dist2, dist, midx, midy,
50109             sqrt = Math.sqrt, abs = Math.abs;
50110
50111         nextItem = items[i];
50112         prevItem = i && items[i - 1];
50113
50114         if (i >= ln) {
50115             prevItem = items[ln - 1];
50116         }
50117         prevPoint = prevItem && prevItem.point;
50118         nextPoint = nextItem && nextItem.point;
50119         x1 = prevItem ? prevPoint[0] : nextPoint[0] - tolerance;
50120         y1 = prevItem ? prevPoint[1] : nextPoint[1];
50121         x2 = nextItem ? nextPoint[0] : prevPoint[0] + tolerance;
50122         y2 = nextItem ? nextPoint[1] : prevPoint[1];
50123         dist1 = sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
50124         dist2 = sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2));
50125         dist = Math.min(dist1, dist2);
50126
50127         if (dist <= tolerance) {
50128             return dist == dist1? prevItem : nextItem;
50129         }
50130         return false;
50131     },
50132
50133     
50134     toggleAll: function(show) {
50135         var me = this,
50136             i, ln, shadow, shadows;
50137         if (!show) {
50138             Ext.chart.series.Cartesian.prototype.hideAll.call(me);
50139         }
50140         else {
50141             Ext.chart.series.Cartesian.prototype.showAll.call(me);
50142         }
50143         if (me.line) {
50144             me.line.setAttributes({
50145                 hidden: !show
50146             }, true);
50147             
50148             if (me.line.shadows) {
50149                 for (i = 0, shadows = me.line.shadows, ln = shadows.length; i < ln; i++) {
50150                     shadow = shadows[i];
50151                     shadow.setAttributes({
50152                         hidden: !show
50153                     }, true);
50154                 }
50155             }
50156         }
50157         if (me.fillPath) {
50158             me.fillPath.setAttributes({
50159                 hidden: !show
50160             }, true);
50161         }
50162     },
50163
50164     
50165     hideAll: function() {
50166         this.toggleAll(false);
50167     },
50168
50169     
50170     showAll: function() {
50171         this.toggleAll(true);
50172     }
50173 });
50174
50175
50176 Ext.define('Ext.chart.series.Pie', {
50177
50178     
50179
50180     alternateClassName: ['Ext.chart.PieSeries', 'Ext.chart.PieChart'],
50181
50182     extend: 'Ext.chart.series.Series',
50183
50184     
50185
50186     type: "pie",
50187
50188     alias: 'series.pie',
50189
50190     rad: Math.PI / 180,
50191
50192     
50193     highlightDuration: 150,
50194
50195     
50196     angleField: false,
50197
50198     
50199     lengthField: false,
50200
50201     
50202     donut: false,
50203
50204     
50205     showInLegend: false,
50206
50207     
50208
50209     
50210     style: {},
50211
50212     constructor: function(config) {
50213         this.callParent(arguments);
50214         var me = this,
50215             chart = me.chart,
50216             surface = chart.surface,
50217             store = chart.store,
50218             shadow = chart.shadow, i, l, cfg;
50219         Ext.applyIf(me, {
50220             highlightCfg: {
50221                 segment: {
50222                     margin: 20
50223                 }
50224             }
50225         });
50226         Ext.apply(me, config, {
50227             shadowAttributes: [{
50228                 "stroke-width": 6,
50229                 "stroke-opacity": 1,
50230                 stroke: 'rgb(200, 200, 200)',
50231                 translate: {
50232                     x: 1.2,
50233                     y: 2
50234                 }
50235             },
50236             {
50237                 "stroke-width": 4,
50238                 "stroke-opacity": 1,
50239                 stroke: 'rgb(150, 150, 150)',
50240                 translate: {
50241                     x: 0.9,
50242                     y: 1.5
50243                 }
50244             },
50245             {
50246                 "stroke-width": 2,
50247                 "stroke-opacity": 1,
50248                 stroke: 'rgb(100, 100, 100)',
50249                 translate: {
50250                     x: 0.6,
50251                     y: 1
50252                 }
50253             }]
50254         });
50255         me.group = surface.getGroup(me.seriesId);
50256         if (shadow) {
50257             for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
50258                 me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
50259             }
50260         }
50261         surface.customAttributes.segment = function(opt) {
50262             return me.getSegment(opt);
50263         };
50264         me.__excludes = me.__excludes || [];
50265     },
50266
50267     //@private updates some onbefore render parameters.
50268
50269     initialize: function() {
50270         var me = this,
50271             store = me.chart.getChartStore();
50272         
50273         me.yField = [];
50274         if (me.label.field) {
50275             store.each(function(rec) {
50276                 me.yField.push(rec.get(me.label.field));
50277             });
50278         }
50279     },
50280
50281     
50282     getSegment: function(opt) {
50283         var me = this,
50284             rad = me.rad,
50285             cos = Math.cos,
50286             sin = Math.sin,
50287             x = me.centerX,
50288             y = me.centerY,
50289             x1 = 0, x2 = 0, x3 = 0, x4 = 0,
50290             y1 = 0, y2 = 0, y3 = 0, y4 = 0,
50291             x5 = 0, y5 = 0, x6 = 0, y6 = 0,
50292             delta = 1e-2,
50293             startAngle = opt.startAngle,
50294             endAngle = opt.endAngle,
50295             midAngle = (startAngle + endAngle) / 2 * rad,
50296             margin = opt.margin || 0,
50297             a1 = Math.min(startAngle, endAngle) * rad,
50298             a2 = Math.max(startAngle, endAngle) * rad,
50299             c1 = cos(a1), s1 = sin(a1),
50300             c2 = cos(a2), s2 = sin(a2),
50301             cm = cos(midAngle), sm = sin(midAngle),
50302             flag = 0, hsqr2 = 0.7071067811865476; 
50303
50304         if (a2 - a1 < delta) {
50305             return {path: ""};
50306         }
50307
50308         if (margin !== 0) {
50309             x += margin * cm;
50310             y += margin * sm;
50311         }
50312
50313         x2 = x + opt.endRho * c1;
50314         y2 = y + opt.endRho * s1;
50315
50316         x4 = x + opt.endRho * c2;
50317         y4 = y + opt.endRho * s2;
50318
50319         if (Math.abs(x2 - x4) + Math.abs(y2 - y4) < delta) {
50320             cm = hsqr2;
50321             sm = -hsqr2;
50322             flag = 1;
50323         }
50324
50325         x6 = x + opt.endRho * cm;
50326         y6 = y + opt.endRho * sm;
50327
50328         
50329         
50330
50331         if (opt.startRho !== 0) {
50332             x1 = x + opt.startRho * c1;
50333             y1 = y + opt.startRho * s1;
50334     
50335             x3 = x + opt.startRho * c2;
50336             y3 = y + opt.startRho * s2;
50337     
50338             x5 = x + opt.startRho * cm;
50339             y5 = y + opt.startRho * sm;
50340
50341             return {
50342                 path: [
50343                     ["M", x2, y2],
50344                     ["A", opt.endRho, opt.endRho, 0, 0, 1, x6, y6], ["L", x6, y6],
50345                     ["A", opt.endRho, opt.endRho, 0, flag, 1, x4, y4], ["L", x4, y4],
50346                     ["L", x3, y3],
50347                     ["A", opt.startRho, opt.startRho, 0, flag, 0, x5, y5], ["L", x5, y5],
50348                     ["A", opt.startRho, opt.startRho, 0, 0, 0, x1, y1], ["L", x1, y1],
50349                     ["Z"]
50350                 ]
50351             };
50352         } else {
50353             return {
50354                 path: [
50355                     ["M", x, y],
50356                     ["L", x2, y2],
50357                     ["A", opt.endRho, opt.endRho, 0, 0, 1, x6, y6], ["L", x6, y6],
50358                     ["A", opt.endRho, opt.endRho, 0, flag, 1, x4, y4], ["L", x4, y4],
50359                     ["L", x, y],
50360                     ["Z"]
50361                 ]
50362             };
50363         }
50364     },
50365
50366     
50367     calcMiddle: function(item) {
50368         var me = this,
50369             rad = me.rad,
50370             slice = item.slice,
50371             x = me.centerX,
50372             y = me.centerY,
50373             startAngle = slice.startAngle,
50374             endAngle = slice.endAngle,
50375             donut = +me.donut,
50376             midAngle = -(startAngle + endAngle) * rad / 2,
50377             r = (item.endRho + item.startRho) / 2,
50378             xm = x + r * Math.cos(midAngle),
50379             ym = y - r * Math.sin(midAngle);
50380
50381         item.middle = {
50382             x: xm,
50383             y: ym
50384         };
50385     },
50386
50387     
50388     drawSeries: function() {
50389         var me = this,
50390             store = me.chart.getChartStore(),
50391             group = me.group,
50392             animate = me.chart.animate,
50393             field = me.angleField || me.field || me.xField,
50394             lenField = [].concat(me.lengthField),
50395             totalLenField = 0,
50396             colors = me.colorSet,
50397             chart = me.chart,
50398             surface = chart.surface,
50399             chartBBox = chart.chartBBox,
50400             enableShadows = chart.shadow,
50401             shadowGroups = me.shadowGroups,
50402             shadowAttributes = me.shadowAttributes,
50403             lnsh = shadowGroups.length,
50404             rad = me.rad,
50405             layers = lenField.length,
50406             rhoAcum = 0,
50407             donut = +me.donut,
50408             layerTotals = [],
50409             values = {},
50410             fieldLength,
50411             items = [],
50412             passed = false,
50413             totalField = 0,
50414             maxLenField = 0,
50415             cut = 9,
50416             defcut = true,
50417             angle = 0,
50418             seriesStyle = me.seriesStyle,
50419             seriesLabelStyle = me.seriesLabelStyle,
50420             colorArrayStyle = me.colorArrayStyle,
50421             colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
50422             gutterX = chart.maxGutter[0],
50423             gutterY = chart.maxGutter[1],
50424             abs = Math.abs,
50425             rendererAttributes,
50426             shadowGroup,
50427             shadowAttr,
50428             shadows,
50429             shadow,
50430             shindex,
50431             centerX,
50432             centerY,
50433             deltaRho,
50434             first = 0,
50435             slice,
50436             slices,
50437             sprite,
50438             value,
50439             item,
50440             lenValue,
50441             ln,
50442             record,
50443             i,
50444             j,
50445             startAngle,
50446             endAngle,
50447             middleAngle,
50448             sliceLength,
50449             path,
50450             p,
50451             spriteOptions, bbox;
50452
50453         Ext.apply(seriesStyle, me.style || {});
50454
50455         me.setBBox();
50456         bbox = me.bbox;
50457
50458         
50459         if (me.colorSet) {
50460             colorArrayStyle = me.colorSet;
50461             colorArrayLength = colorArrayStyle.length;
50462         }
50463
50464         
50465         if (!store || !store.getCount()) {
50466             return;
50467         }
50468
50469         me.unHighlightItem();
50470         me.cleanHighlights();
50471
50472         centerX = me.centerX = chartBBox.x + (chartBBox.width / 2);
50473         centerY = me.centerY = chartBBox.y + (chartBBox.height / 2);
50474         me.radius = Math.min(centerX - chartBBox.x, centerY - chartBBox.y);
50475         me.slices = slices = [];
50476         me.items = items = [];
50477
50478         store.each(function(record, i) {
50479             if (this.__excludes && this.__excludes[i]) {
50480                 
50481                 return;
50482             }
50483             totalField += +record.get(field);
50484             if (lenField[0]) {
50485                 for (j = 0, totalLenField = 0; j < layers; j++) {
50486                     totalLenField += +record.get(lenField[j]);
50487                 }
50488                 layerTotals[i] = totalLenField;
50489                 maxLenField = Math.max(maxLenField, totalLenField);
50490             }
50491         }, this);
50492
50493         totalField = totalField || 1;
50494         store.each(function(record, i) {
50495             if (this.__excludes && this.__excludes[i]) {
50496                 value = 0;
50497             } else {
50498                 value = record.get(field);
50499                 if (first == 0) {
50500                     first = 1;
50501                 }
50502             }
50503
50504             
50505             if (first == 1) {
50506                 first = 2;
50507                 me.firstAngle = angle = 360 * value / totalField / 2;
50508                 for (j = 0; j < i; j++) {
50509                     slices[j].startAngle = slices[j].endAngle = me.firstAngle;
50510                 }
50511             }
50512             
50513             endAngle = angle - 360 * value / totalField;
50514             slice = {
50515                 series: me,
50516                 value: value,
50517                 startAngle: angle,
50518                 endAngle: endAngle,
50519                 storeItem: record
50520             };
50521             if (lenField[0]) {
50522                 lenValue = layerTotals[i];
50523                 slice.rho = me.radius * (lenValue / maxLenField);
50524             } else {
50525                 slice.rho = me.radius;
50526             }
50527             slices[i] = slice;
50528             angle = endAngle;
50529         }, me);
50530         
50531         if (enableShadows) {
50532             for (i = 0, ln = slices.length; i < ln; i++) {
50533                 slice = slices[i];
50534                 slice.shadowAttrs = [];
50535                 for (j = 0, rhoAcum = 0, shadows = []; j < layers; j++) {
50536                     sprite = group.getAt(i * layers + j);
50537                     deltaRho = lenField[j] ? store.getAt(i).get(lenField[j]) / layerTotals[i] * slice.rho: slice.rho;
50538                     
50539                     rendererAttributes = {
50540                         segment: {
50541                             startAngle: slice.startAngle,
50542                             endAngle: slice.endAngle,
50543                             margin: 0,
50544                             rho: slice.rho,
50545                             startRho: rhoAcum + (deltaRho * donut / 100),
50546                             endRho: rhoAcum + deltaRho
50547                         },
50548                         hidden: !slice.value && (slice.startAngle % 360) == (slice.endAngle % 360)
50549                     };
50550                     
50551                     for (shindex = 0, shadows = []; shindex < lnsh; shindex++) {
50552                         shadowAttr = shadowAttributes[shindex];
50553                         shadow = shadowGroups[shindex].getAt(i);
50554                         if (!shadow) {
50555                             shadow = chart.surface.add(Ext.apply({}, {
50556                                 type: 'path',
50557                                 group: shadowGroups[shindex],
50558                                 strokeLinejoin: "round"
50559                             }, rendererAttributes, shadowAttr));
50560                         }
50561                         if (animate) {
50562                             shadowAttr = me.renderer(shadow, store.getAt(i), Ext.apply({}, rendererAttributes, shadowAttr), i, store);
50563                             me.onAnimate(shadow, {
50564                                 to: shadowAttr
50565                             });
50566                         } else {
50567                             shadowAttr = me.renderer(shadow, store.getAt(i), shadowAttr, i, store);
50568                             shadow.setAttributes(shadowAttr, true);
50569                         }
50570                         shadows.push(shadow);
50571                     }
50572                     slice.shadowAttrs[j] = shadows;
50573                 }
50574             }
50575         }
50576         
50577         for (i = 0, ln = slices.length; i < ln; i++) {
50578             slice = slices[i];
50579             for (j = 0, rhoAcum = 0; j < layers; j++) {
50580                 sprite = group.getAt(i * layers + j);
50581                 deltaRho = lenField[j] ? store.getAt(i).get(lenField[j]) / layerTotals[i] * slice.rho: slice.rho;
50582                 
50583                 rendererAttributes = Ext.apply({
50584                     segment: {
50585                         startAngle: slice.startAngle,
50586                         endAngle: slice.endAngle,
50587                         margin: 0,
50588                         rho: slice.rho,
50589                         startRho: rhoAcum + (deltaRho * donut / 100),
50590                         endRho: rhoAcum + deltaRho
50591                     },
50592                     hidden: (!slice.value && (slice.startAngle % 360) == (slice.endAngle % 360))
50593                 }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[(layers > 1? j : i) % colorArrayLength] } || {}));
50594                 item = Ext.apply({},
50595                 rendererAttributes.segment, {
50596                     slice: slice,
50597                     series: me,
50598                     storeItem: slice.storeItem,
50599                     index: i
50600                 });
50601                 me.calcMiddle(item);
50602                 if (enableShadows) {
50603                     item.shadows = slice.shadowAttrs[j];
50604                 }
50605                 items[i] = item;
50606                 
50607                 if (!sprite) {
50608                     spriteOptions = Ext.apply({
50609                         type: "path",
50610                         group: group,
50611                         middle: item.middle
50612                     }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[(layers > 1? j : i) % colorArrayLength] } || {}));
50613                     sprite = surface.add(Ext.apply(spriteOptions, rendererAttributes));
50614                 }
50615                 slice.sprite = slice.sprite || [];
50616                 item.sprite = sprite;
50617                 slice.sprite.push(sprite);
50618                 slice.point = [item.middle.x, item.middle.y];
50619                 if (animate) {
50620                     rendererAttributes = me.renderer(sprite, store.getAt(i), rendererAttributes, i, store);
50621                     sprite._to = rendererAttributes;
50622                     sprite._animating = true;
50623                     me.onAnimate(sprite, {
50624                         to: rendererAttributes,
50625                         listeners: {
50626                             afteranimate: {
50627                                 fn: function() {
50628                                     this._animating = false;
50629                                 },
50630                                 scope: sprite
50631                             }
50632                         }
50633                     });
50634                 } else {
50635                     rendererAttributes = me.renderer(sprite, store.getAt(i), Ext.apply(rendererAttributes, {
50636                         hidden: false
50637                     }), i, store);
50638                     sprite.setAttributes(rendererAttributes, true);
50639                 }
50640                 rhoAcum += deltaRho;
50641             }
50642         }
50643
50644         
50645         ln = group.getCount();
50646         for (i = 0; i < ln; i++) {
50647             if (!slices[(i / layers) >> 0] && group.getAt(i)) {
50648                 group.getAt(i).hide(true);
50649             }
50650         }
50651         if (enableShadows) {
50652             lnsh = shadowGroups.length;
50653             for (shindex = 0; shindex < ln; shindex++) {
50654                 if (!slices[(shindex / layers) >> 0]) {
50655                     for (j = 0; j < lnsh; j++) {
50656                         if (shadowGroups[j].getAt(shindex)) {
50657                             shadowGroups[j].getAt(shindex).hide(true);
50658                         }
50659                     }
50660                 }
50661             }
50662         }
50663         me.renderLabels();
50664         me.renderCallouts();
50665     },
50666
50667     
50668     onCreateLabel: function(storeItem, item, i, display) {
50669         var me = this,
50670             group = me.labelsGroup,
50671             config = me.label,
50672             centerX = me.centerX,
50673             centerY = me.centerY,
50674             middle = item.middle,
50675             endLabelStyle = Ext.apply(me.seriesLabelStyle || {}, config || {});
50676
50677         return me.chart.surface.add(Ext.apply({
50678             'type': 'text',
50679             'text-anchor': 'middle',
50680             'group': group,
50681             'x': middle.x,
50682             'y': middle.y
50683         }, endLabelStyle));
50684     },
50685
50686     
50687     onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {
50688         var me = this,
50689             chart = me.chart,
50690             resizing = chart.resizing,
50691             config = me.label,
50692             format = config.renderer,
50693             field = [].concat(config.field),
50694             centerX = me.centerX,
50695             centerY = me.centerY,
50696             middle = item.middle,
50697             opt = {
50698                 x: middle.x,
50699                 y: middle.y
50700             },
50701             x = middle.x - centerX,
50702             y = middle.y - centerY,
50703             from = {},
50704             rho = 1,
50705             theta = Math.atan2(y, x || 1),
50706             dg = theta * 180 / Math.PI,
50707             prevDg;
50708         if (this.__excludes && this.__excludes[i]) {
50709             opt.hidden = true;
50710         }
50711         function fixAngle(a) {
50712             if (a < 0) {
50713                 a += 360;
50714             }
50715             return a % 360;
50716         }
50717
50718         label.setAttributes({
50719             text: format(storeItem.get(field[index]))
50720         }, true);
50721
50722         switch (display) {
50723         case 'outside':
50724             rho = Math.sqrt(x * x + y * y) * 2;
50725             
50726             opt.x = rho * Math.cos(theta) + centerX;
50727             opt.y = rho * Math.sin(theta) + centerY;
50728             break;
50729
50730         case 'rotate':
50731             dg = fixAngle(dg);
50732             dg = (dg > 90 && dg < 270) ? dg + 180: dg;
50733
50734             prevDg = label.attr.rotation.degrees;
50735             if (prevDg != null && Math.abs(prevDg - dg) > 180) {
50736                 if (dg > prevDg) {
50737                     dg -= 360;
50738                 } else {
50739                     dg += 360;
50740                 }
50741                 dg = dg % 360;
50742             } else {
50743                 dg = fixAngle(dg);
50744             }
50745             
50746             opt.rotate = {
50747                 degrees: dg,
50748                 x: opt.x,
50749                 y: opt.y
50750             };
50751             break;
50752
50753         default:
50754             break;
50755         }
50756         
50757         opt.translate = {
50758             x: 0, y: 0
50759         };
50760         if (animate && !resizing && (display != 'rotate' || prevDg != null)) {
50761             me.onAnimate(label, {
50762                 to: opt
50763             });
50764         } else {
50765             label.setAttributes(opt, true);
50766         }
50767         label._from = from;
50768     },
50769
50770     
50771     onPlaceCallout: function(callout, storeItem, item, i, display, animate, index) {
50772         var me = this,
50773             chart = me.chart,
50774             resizing = chart.resizing,
50775             config = me.callouts,
50776             centerX = me.centerX,
50777             centerY = me.centerY,
50778             middle = item.middle,
50779             opt = {
50780                 x: middle.x,
50781                 y: middle.y
50782             },
50783             x = middle.x - centerX,
50784             y = middle.y - centerY,
50785             rho = 1,
50786             rhoCenter,
50787             theta = Math.atan2(y, x || 1),
50788             bbox = callout.label.getBBox(),
50789             offsetFromViz = 20,
50790             offsetToSide = 10,
50791             offsetBox = 10,
50792             p;
50793
50794         
50795         rho = item.endRho + offsetFromViz;
50796         rhoCenter = (item.endRho + item.startRho) / 2 + (item.endRho - item.startRho) / 3;
50797         
50798         opt.x = rho * Math.cos(theta) + centerX;
50799         opt.y = rho * Math.sin(theta) + centerY;
50800
50801         x = rhoCenter * Math.cos(theta);
50802         y = rhoCenter * Math.sin(theta);
50803
50804         if (chart.animate) {
50805             
50806             me.onAnimate(callout.lines, {
50807                 to: {
50808                     path: ["M", x + centerX, y + centerY, "L", opt.x, opt.y, "Z", "M", opt.x, opt.y, "l", x > 0 ? offsetToSide: -offsetToSide, 0, "z"]
50809                 }
50810             });
50811             
50812             me.onAnimate(callout.box, {
50813                 to: {
50814                     x: opt.x + (x > 0 ? offsetToSide: -(offsetToSide + bbox.width + 2 * offsetBox)),
50815                     y: opt.y + (y > 0 ? ( - bbox.height - offsetBox / 2) : ( - bbox.height - offsetBox / 2)),
50816                     width: bbox.width + 2 * offsetBox,
50817                     height: bbox.height + 2 * offsetBox
50818                 }
50819             });
50820             
50821             me.onAnimate(callout.label, {
50822                 to: {
50823                     x: opt.x + (x > 0 ? (offsetToSide + offsetBox) : -(offsetToSide + bbox.width + offsetBox)),
50824                     y: opt.y + (y > 0 ? -bbox.height / 4: -bbox.height / 4)
50825                 }
50826             });
50827         } else {
50828             
50829             callout.lines.setAttributes({
50830                 path: ["M", x + centerX, y + centerY, "L", opt.x, opt.y, "Z", "M", opt.x, opt.y, "l", x > 0 ? offsetToSide: -offsetToSide, 0, "z"]
50831             },
50832             true);
50833             
50834             callout.box.setAttributes({
50835                 x: opt.x + (x > 0 ? offsetToSide: -(offsetToSide + bbox.width + 2 * offsetBox)),
50836                 y: opt.y + (y > 0 ? ( - bbox.height - offsetBox / 2) : ( - bbox.height - offsetBox / 2)),
50837                 width: bbox.width + 2 * offsetBox,
50838                 height: bbox.height + 2 * offsetBox
50839             },
50840             true);
50841             
50842             callout.label.setAttributes({
50843                 x: opt.x + (x > 0 ? (offsetToSide + offsetBox) : -(offsetToSide + bbox.width + offsetBox)),
50844                 y: opt.y + (y > 0 ? -bbox.height / 4: -bbox.height / 4)
50845             },
50846             true);
50847         }
50848         for (p in callout) {
50849             callout[p].show(true);
50850         }
50851     },
50852
50853     
50854     onAnimate: function(sprite, attr) {
50855         sprite.show();
50856         return this.callParent(arguments);
50857     },
50858
50859     isItemInPoint: function(x, y, item, i) {
50860         var me = this,
50861             cx = me.centerX,
50862             cy = me.centerY,
50863             abs = Math.abs,
50864             dx = abs(x - cx),
50865             dy = abs(y - cy),
50866             startAngle = item.startAngle,
50867             endAngle = item.endAngle,
50868             rho = Math.sqrt(dx * dx + dy * dy),
50869             angle = Math.atan2(y - cy, x - cx) / me.rad;
50870
50871         
50872         if (angle > me.firstAngle) {
50873             angle -= 360;
50874         }
50875         return (angle <= startAngle && angle > endAngle
50876                 && rho >= item.startRho && rho <= item.endRho);
50877     },
50878
50879     
50880     hideAll: function() {
50881         var i, l, shadow, shadows, sh, lsh, sprite;
50882         if (!isNaN(this._index)) {
50883             this.__excludes = this.__excludes || [];
50884             this.__excludes[this._index] = true;
50885             sprite = this.slices[this._index].sprite;
50886             for (sh = 0, lsh = sprite.length; sh < lsh; sh++) {
50887                 sprite[sh].setAttributes({
50888                     hidden: true
50889                 }, true);
50890             }
50891             if (this.slices[this._index].shadowAttrs) {
50892                 for (i = 0, shadows = this.slices[this._index].shadowAttrs, l = shadows.length; i < l; i++) {
50893                     shadow = shadows[i];
50894                     for (sh = 0, lsh = shadow.length; sh < lsh; sh++) {
50895                         shadow[sh].setAttributes({
50896                             hidden: true
50897                         }, true);
50898                     }
50899                 }
50900             }
50901             this.drawSeries();
50902         }
50903     },
50904
50905     
50906     showAll: function() {
50907         if (!isNaN(this._index)) {
50908             this.__excludes[this._index] = false;
50909             this.drawSeries();
50910         }
50911     },
50912
50913     
50914     highlightItem: function(item) {
50915         var me = this,
50916             rad = me.rad;
50917         item = item || this.items[this._index];
50918
50919         
50920         
50921         
50922         
50923         this.unHighlightItem();
50924
50925         if (!item || item.sprite && item.sprite._animating) {
50926             return;
50927         }
50928         me.callParent([item]);
50929         if (!me.highlight) {
50930             return;
50931         }
50932         if ('segment' in me.highlightCfg) {
50933             var highlightSegment = me.highlightCfg.segment,
50934                 animate = me.chart.animate,
50935                 attrs, i, shadows, shadow, ln, to, itemHighlightSegment, prop;
50936             
50937             if (me.labelsGroup) {
50938                 var group = me.labelsGroup,
50939                     display = me.label.display,
50940                     label = group.getAt(item.index),
50941                     middle = (item.startAngle + item.endAngle) / 2 * rad,
50942                     r = highlightSegment.margin || 0,
50943                     x = r * Math.cos(middle),
50944                     y = r * Math.sin(middle);
50945
50946                 
50947                 
50948                 
50949                 
50950                 
50951                 if (Math.abs(x) < 1e-10) {
50952                     x = 0;
50953                 }
50954                 if (Math.abs(y) < 1e-10) {
50955                     y = 0;
50956                 }
50957
50958                 if (animate) {
50959                     label.stopAnimation();
50960                     label.animate({
50961                         to: {
50962                             translate: {
50963                                 x: x,
50964                                 y: y
50965                             }
50966                         },
50967                         duration: me.highlightDuration
50968                     });
50969                 }
50970                 else {
50971                     label.setAttributes({
50972                         translate: {
50973                             x: x,
50974                             y: y
50975                         }
50976                     }, true);
50977                 }
50978             }
50979             
50980             if (me.chart.shadow && item.shadows) {
50981                 i = 0;
50982                 shadows = item.shadows;
50983                 ln = shadows.length;
50984                 for (; i < ln; i++) {
50985                     shadow = shadows[i];
50986                     to = {};
50987                     itemHighlightSegment = item.sprite._from.segment;
50988                     for (prop in itemHighlightSegment) {
50989                         if (! (prop in highlightSegment)) {
50990                             to[prop] = itemHighlightSegment[prop];
50991                         }
50992                     }
50993                     attrs = {
50994                         segment: Ext.applyIf(to, me.highlightCfg.segment)
50995                     };
50996                     if (animate) {
50997                         shadow.stopAnimation();
50998                         shadow.animate({
50999                             to: attrs,
51000                             duration: me.highlightDuration
51001                         });
51002                     }
51003                     else {
51004                         shadow.setAttributes(attrs, true);
51005                     }
51006                 }
51007             }
51008         }
51009     },
51010
51011     
51012     unHighlightItem: function() {
51013         var me = this;
51014         if (!me.highlight) {
51015             return;
51016         }
51017
51018         if (('segment' in me.highlightCfg) && me.items) {
51019             var items = me.items,
51020                 animate = me.chart.animate,
51021                 shadowsEnabled = !!me.chart.shadow,
51022                 group = me.labelsGroup,
51023                 len = items.length,
51024                 i = 0,
51025                 j = 0,
51026                 display = me.label.display,
51027                 shadowLen, p, to, ihs, hs, sprite, shadows, shadow, item, label, attrs;
51028
51029             for (; i < len; i++) {
51030                 item = items[i];
51031                 if (!item) {
51032                     continue;
51033                 }
51034                 sprite = item.sprite;
51035                 if (sprite && sprite._highlighted) {
51036                     
51037                     if (group) {
51038                         label = group.getAt(item.index);
51039                         attrs = Ext.apply({
51040                             translate: {
51041                                 x: 0,
51042                                 y: 0
51043                             }
51044                         },
51045                         display == 'rotate' ? {
51046                             rotate: {
51047                                 x: label.attr.x,
51048                                 y: label.attr.y,
51049                                 degrees: label.attr.rotation.degrees
51050                             }
51051                         }: {});
51052                         if (animate) {
51053                             label.stopAnimation();
51054                             label.animate({
51055                                 to: attrs,
51056                                 duration: me.highlightDuration
51057                             });
51058                         }
51059                         else {
51060                             label.setAttributes(attrs, true);
51061                         }
51062                     }
51063                     if (shadowsEnabled) {
51064                         shadows = item.shadows;
51065                         shadowLen = shadows.length;
51066                         for (; j < shadowLen; j++) {
51067                             to = {};
51068                             ihs = item.sprite._to.segment;
51069                             hs = item.sprite._from.segment;
51070                             Ext.apply(to, hs);
51071                             for (p in ihs) {
51072                                 if (! (p in hs)) {
51073                                     to[p] = ihs[p];
51074                                 }
51075                             }
51076                             shadow = shadows[j];
51077                             if (animate) {
51078                                 shadow.stopAnimation();
51079                                 shadow.animate({
51080                                     to: {
51081                                         segment: to
51082                                     },
51083                                     duration: me.highlightDuration
51084                                 });
51085                             }
51086                             else {
51087                                 shadow.setAttributes({ segment: to }, true);
51088                             }
51089                         }
51090                     }
51091                 }
51092             }
51093         }
51094         me.callParent(arguments);
51095     },
51096
51097     
51098     getLegendColor: function(index) {
51099         var me = this;
51100         return (me.colorSet && me.colorSet[index % me.colorSet.length]) || me.colorArrayStyle[index % me.colorArrayStyle.length];
51101     }
51102 });
51103
51104
51105
51106 Ext.define('Ext.chart.series.Radar', {
51107
51108     
51109
51110     extend: 'Ext.chart.series.Series',
51111
51112     requires: ['Ext.chart.Shape', 'Ext.fx.Anim'],
51113
51114     
51115
51116     type: "radar",
51117     alias: 'series.radar',
51118
51119
51120     rad: Math.PI / 180,
51121
51122     showInLegend: false,
51123
51124     
51125     style: {},
51126
51127     constructor: function(config) {
51128         this.callParent(arguments);
51129         var me = this,
51130             surface = me.chart.surface, i, l;
51131         me.group = surface.getGroup(me.seriesId);
51132         if (me.showMarkers) {
51133             me.markerGroup = surface.getGroup(me.seriesId + '-markers');
51134         }
51135     },
51136
51137     
51138     drawSeries: function() {
51139         var me = this,
51140             store = me.chart.getChartStore(),
51141             group = me.group,
51142             sprite,
51143             chart = me.chart,
51144             animate = chart.animate,
51145             field = me.field || me.yField,
51146             surface = chart.surface,
51147             chartBBox = chart.chartBBox,
51148             rendererAttributes,
51149             centerX, centerY,
51150             items,
51151             radius,
51152             maxValue = 0,
51153             fields = [],
51154             max = Math.max,
51155             cos = Math.cos,
51156             sin = Math.sin,
51157             pi2 = Math.PI * 2,
51158             l = store.getCount(),
51159             startPath, path, x, y, rho,
51160             i, nfields,
51161             seriesStyle = me.seriesStyle,
51162             seriesLabelStyle = me.seriesLabelStyle,
51163             first = chart.resizing || !me.radar,
51164             axis = chart.axes && chart.axes.get(0),
51165             aggregate = !(axis && axis.maximum);
51166
51167         me.setBBox();
51168
51169         maxValue = aggregate? 0 : (axis.maximum || 0);
51170
51171         Ext.apply(seriesStyle, me.style || {});
51172
51173         
51174         if (!store || !store.getCount()) {
51175             return;
51176         }
51177
51178         me.unHighlightItem();
51179         me.cleanHighlights();
51180
51181         centerX = me.centerX = chartBBox.x + (chartBBox.width / 2);
51182         centerY = me.centerY = chartBBox.y + (chartBBox.height / 2);
51183         me.radius = radius = Math.min(chartBBox.width, chartBBox.height) /2;
51184         me.items = items = [];
51185
51186         if (aggregate) {
51187             
51188             chart.series.each(function(series) {
51189                 fields.push(series.yField);
51190             });
51191             
51192             store.each(function(record, i) {
51193                 for (i = 0, nfields = fields.length; i < nfields; i++) {
51194                     maxValue = max(+record.get(fields[i]), maxValue);
51195                 }
51196             });
51197         }
51198         
51199         maxValue = maxValue || 1;
51200         
51201         startPath = []; path = [];
51202         store.each(function(record, i) {
51203             rho = radius * record.get(field) / maxValue;
51204             x = rho * cos(i / l * pi2);
51205             y = rho * sin(i / l * pi2);
51206             if (i == 0) {
51207                 path.push('M', x + centerX, y + centerY);
51208                 startPath.push('M', 0.01 * x + centerX, 0.01 * y + centerY);
51209             } else {
51210                 path.push('L', x + centerX, y + centerY);
51211                 startPath.push('L', 0.01 * x + centerX, 0.01 * y + centerY);
51212             }
51213             items.push({
51214                 sprite: false, 
51215                 point: [centerX + x, centerY + y],
51216                 series: me
51217             });
51218         });
51219         path.push('Z');
51220         
51221         if (!me.radar) {
51222             me.radar = surface.add(Ext.apply({
51223                 type: 'path',
51224                 group: group,
51225                 path: startPath
51226             }, seriesStyle || {}));
51227         }
51228         
51229         if (chart.resizing) {
51230             me.radar.setAttributes({
51231                 path: startPath
51232             }, true);
51233         }
51234         
51235         if (chart.animate) {
51236             me.onAnimate(me.radar, {
51237                 to: Ext.apply({
51238                     path: path
51239                 }, seriesStyle || {})
51240             });
51241         } else {
51242             me.radar.setAttributes(Ext.apply({
51243                 path: path
51244             }, seriesStyle || {}), true);
51245         }
51246         
51247         if (me.showMarkers) {
51248             me.drawMarkers();
51249         }
51250         me.renderLabels();
51251         me.renderCallouts();
51252     },
51253
51254     
51255     drawMarkers: function() {
51256         var me = this,
51257             chart = me.chart,
51258             surface = chart.surface,
51259             markerStyle = Ext.apply({}, me.markerStyle || {}),
51260             endMarkerStyle = Ext.apply(markerStyle, me.markerConfig),
51261             items = me.items,
51262             type = endMarkerStyle.type,
51263             markerGroup = me.markerGroup,
51264             centerX = me.centerX,
51265             centerY = me.centerY,
51266             item, i, l, marker;
51267
51268         delete endMarkerStyle.type;
51269
51270         for (i = 0, l = items.length; i < l; i++) {
51271             item = items[i];
51272             marker = markerGroup.getAt(i);
51273             if (!marker) {
51274                 marker = Ext.chart.Shape[type](surface, Ext.apply({
51275                     group: markerGroup,
51276                     x: 0,
51277                     y: 0,
51278                     translate: {
51279                         x: centerX,
51280                         y: centerY
51281                     }
51282                 }, endMarkerStyle));
51283             }
51284             else {
51285                 marker.show();
51286             }
51287             if (chart.resizing) {
51288                 marker.setAttributes({
51289                     x: 0,
51290                     y: 0,
51291                     translate: {
51292                         x: centerX,
51293                         y: centerY
51294                     }
51295                 }, true);
51296             }
51297             marker._to = {
51298                 translate: {
51299                     x: item.point[0],
51300                     y: item.point[1]
51301                 }
51302             };
51303             
51304             if (chart.animate) {
51305                 me.onAnimate(marker, {
51306                     to: marker._to
51307                 });
51308             }
51309             else {
51310                 marker.setAttributes(Ext.apply(marker._to, endMarkerStyle || {}), true);
51311             }
51312         }
51313     },
51314
51315     isItemInPoint: function(x, y, item) {
51316         var point,
51317             tolerance = 10,
51318             abs = Math.abs;
51319         point = item.point;
51320         return (abs(point[0] - x) <= tolerance &&
51321                 abs(point[1] - y) <= tolerance);
51322     },
51323
51324     
51325     onCreateLabel: function(storeItem, item, i, display) {
51326         var me = this,
51327             group = me.labelsGroup,
51328             config = me.label,
51329             centerX = me.centerX,
51330             centerY = me.centerY,
51331             point = item.point,
51332             endLabelStyle = Ext.apply(me.seriesLabelStyle || {}, config);
51333
51334         return me.chart.surface.add(Ext.apply({
51335             'type': 'text',
51336             'text-anchor': 'middle',
51337             'group': group,
51338             'x': centerX,
51339             'y': centerY
51340         }, config || {}));
51341     },
51342
51343     
51344     onPlaceLabel: function(label, storeItem, item, i, display, animate) {
51345         var me = this,
51346             chart = me.chart,
51347             resizing = chart.resizing,
51348             config = me.label,
51349             format = config.renderer,
51350             field = config.field,
51351             centerX = me.centerX,
51352             centerY = me.centerY,
51353             opt = {
51354                 x: item.point[0],
51355                 y: item.point[1]
51356             },
51357             x = opt.x - centerX,
51358             y = opt.y - centerY;
51359
51360         label.setAttributes({
51361             text: format(storeItem.get(field)),
51362             hidden: true
51363         },
51364         true);
51365
51366         if (resizing) {
51367             label.setAttributes({
51368                 x: centerX,
51369                 y: centerY
51370             }, true);
51371         }
51372
51373         if (animate) {
51374             label.show(true);
51375             me.onAnimate(label, {
51376                 to: opt
51377             });
51378         } else {
51379             label.setAttributes(opt, true);
51380             label.show(true);
51381         }
51382     },
51383
51384     
51385     toggleAll: function(show) {
51386         var me = this,
51387             i, ln, shadow, shadows;
51388         if (!show) {
51389             Ext.chart.series.Radar.superclass.hideAll.call(me);
51390         }
51391         else {
51392             Ext.chart.series.Radar.superclass.showAll.call(me);
51393         }
51394         if (me.radar) {
51395             me.radar.setAttributes({
51396                 hidden: !show
51397             }, true);
51398             
51399             if (me.radar.shadows) {
51400                 for (i = 0, shadows = me.radar.shadows, ln = shadows.length; i < ln; i++) {
51401                     shadow = shadows[i];
51402                     shadow.setAttributes({
51403                         hidden: !show
51404                     }, true);
51405                 }
51406             }
51407         }
51408     },
51409
51410     
51411     hideAll: function() {
51412         this.toggleAll(false);
51413         this.hideMarkers(0);
51414     },
51415
51416     
51417     showAll: function() {
51418         this.toggleAll(true);
51419     },
51420
51421     
51422     hideMarkers: function(index) {
51423         var me = this,
51424             count = me.markerGroup && me.markerGroup.getCount() || 0,
51425             i = index || 0;
51426         for (; i < count; i++) {
51427             me.markerGroup.getAt(i).hide(true);
51428         }
51429     }
51430 });
51431
51432
51433
51434 Ext.define('Ext.chart.series.Scatter', {
51435
51436     
51437
51438     extend: 'Ext.chart.series.Cartesian',
51439
51440     requires: ['Ext.chart.axis.Axis', 'Ext.chart.Shape', 'Ext.fx.Anim'],
51441
51442     
51443
51444     type: 'scatter',
51445     alias: 'series.scatter',
51446
51447     
51448
51449     
51450     
51451     
51452
51453     constructor: function(config) {
51454         this.callParent(arguments);
51455         var me = this,
51456             shadow = me.chart.shadow,
51457             surface = me.chart.surface, i, l;
51458         Ext.apply(me, config, {
51459             style: {},
51460             markerConfig: {},
51461             shadowAttributes: [{
51462                 "stroke-width": 6,
51463                 "stroke-opacity": 0.05,
51464                 stroke: 'rgb(0, 0, 0)'
51465             }, {
51466                 "stroke-width": 4,
51467                 "stroke-opacity": 0.1,
51468                 stroke: 'rgb(0, 0, 0)'
51469             }, {
51470                 "stroke-width": 2,
51471                 "stroke-opacity": 0.15,
51472                 stroke: 'rgb(0, 0, 0)'
51473             }]
51474         });
51475         me.group = surface.getGroup(me.seriesId);
51476         if (shadow) {
51477             for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
51478                 me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
51479             }
51480         }
51481     },
51482
51483     
51484     getBounds: function() {
51485         var me = this,
51486             chart = me.chart,
51487             store = chart.getChartStore(),
51488             axes = [].concat(me.axis),
51489             bbox, xScale, yScale, ln, minX, minY, maxX, maxY, i, axis, ends;
51490
51491         me.setBBox();
51492         bbox = me.bbox;
51493
51494         for (i = 0, ln = axes.length; i < ln; i++) {
51495             axis = chart.axes.get(axes[i]);
51496             if (axis) {
51497                 ends = axis.calcEnds();
51498                 if (axis.position == 'top' || axis.position == 'bottom') {
51499                     minX = ends.from;
51500                     maxX = ends.to;
51501                 }
51502                 else {
51503                     minY = ends.from;
51504                     maxY = ends.to;
51505                 }
51506             }
51507         }
51508         
51509         if (me.xField && !Ext.isNumber(minX)) {
51510             axis = Ext.create('Ext.chart.axis.Axis', {
51511                 chart: chart,
51512                 fields: [].concat(me.xField)
51513             }).calcEnds();
51514             minX = axis.from;
51515             maxX = axis.to;
51516         }
51517         if (me.yField && !Ext.isNumber(minY)) {
51518             axis = Ext.create('Ext.chart.axis.Axis', {
51519                 chart: chart,
51520                 fields: [].concat(me.yField)
51521             }).calcEnds();
51522             minY = axis.from;
51523             maxY = axis.to;
51524         }
51525
51526         if (isNaN(minX)) {
51527             minX = 0;
51528             maxX = store.getCount() - 1;
51529             xScale = bbox.width / (store.getCount() - 1);
51530         }
51531         else {
51532             xScale = bbox.width / (maxX - minX);
51533         }
51534
51535         if (isNaN(minY)) {
51536             minY = 0;
51537             maxY = store.getCount() - 1;
51538             yScale = bbox.height / (store.getCount() - 1);
51539         }
51540         else {
51541             yScale = bbox.height / (maxY - minY);
51542         }
51543
51544         return {
51545             bbox: bbox,
51546             minX: minX,
51547             minY: minY,
51548             xScale: xScale,
51549             yScale: yScale
51550         };
51551     },
51552
51553     
51554     getPaths: function() {
51555         var me = this,
51556             chart = me.chart,
51557             enableShadows = chart.shadow,
51558             store = chart.getChartStore(),
51559             group = me.group,
51560             bounds = me.bounds = me.getBounds(),
51561             bbox = me.bbox,
51562             xScale = bounds.xScale,
51563             yScale = bounds.yScale,
51564             minX = bounds.minX,
51565             minY = bounds.minY,
51566             boxX = bbox.x,
51567             boxY = bbox.y,
51568             boxHeight = bbox.height,
51569             items = me.items = [],
51570             attrs = [],
51571             x, y, xValue, yValue, sprite;
51572
51573         store.each(function(record, i) {
51574             xValue = record.get(me.xField);
51575             yValue = record.get(me.yField);
51576             
51577             if (typeof yValue == 'undefined' || (typeof yValue == 'string' && !yValue)) {
51578                 return;
51579             }
51580             
51581             if (typeof xValue == 'string' || typeof xValue == 'object' && !Ext.isDate(xValue)) {
51582                 xValue = i;
51583             }
51584             if (typeof yValue == 'string' || typeof yValue == 'object' && !Ext.isDate(yValue)) {
51585                 yValue = i;
51586             }
51587             x = boxX + (xValue - minX) * xScale;
51588             y = boxY + boxHeight - (yValue - minY) * yScale;
51589             attrs.push({
51590                 x: x,
51591                 y: y
51592             });
51593
51594             me.items.push({
51595                 series: me,
51596                 value: [xValue, yValue],
51597                 point: [x, y],
51598                 storeItem: record
51599             });
51600
51601             
51602             if (chart.animate && chart.resizing) {
51603                 sprite = group.getAt(i);
51604                 if (sprite) {
51605                     me.resetPoint(sprite);
51606                     if (enableShadows) {
51607                         me.resetShadow(sprite);
51608                     }
51609                 }
51610             }
51611         });
51612         return attrs;
51613     },
51614
51615     
51616     resetPoint: function(sprite) {
51617         var bbox = this.bbox;
51618         sprite.setAttributes({
51619             translate: {
51620                 x: (bbox.x + bbox.width) / 2,
51621                 y: (bbox.y + bbox.height) / 2
51622             }
51623         }, true);
51624     },
51625
51626     
51627     resetShadow: function(sprite) {
51628         var me = this,
51629             shadows = sprite.shadows,
51630             shadowAttributes = me.shadowAttributes,
51631             ln = me.shadowGroups.length,
51632             bbox = me.bbox,
51633             i, attr;
51634         for (i = 0; i < ln; i++) {
51635             attr = Ext.apply({}, shadowAttributes[i]);
51636             if (attr.translate) {
51637                 attr.translate.x += (bbox.x + bbox.width) / 2;
51638                 attr.translate.y += (bbox.y + bbox.height) / 2;
51639             }
51640             else {
51641                 attr.translate = {
51642                     x: (bbox.x + bbox.width) / 2,
51643                     y: (bbox.y + bbox.height) / 2
51644                 };
51645             }
51646             shadows[i].setAttributes(attr, true);
51647         }
51648     },
51649
51650     
51651     createPoint: function(attr, type) {
51652         var me = this,
51653             chart = me.chart,
51654             group = me.group,
51655             bbox = me.bbox;
51656
51657         return Ext.chart.Shape[type](chart.surface, Ext.apply({}, {
51658             x: 0,
51659             y: 0,
51660             group: group,
51661             translate: {
51662                 x: (bbox.x + bbox.width) / 2,
51663                 y: (bbox.y + bbox.height) / 2
51664             }
51665         }, attr));
51666     },
51667
51668     
51669     createShadow: function(sprite, endMarkerStyle, type) {
51670         var me = this,
51671             chart = me.chart,
51672             shadowGroups = me.shadowGroups,
51673             shadowAttributes = me.shadowAttributes,
51674             lnsh = shadowGroups.length,
51675             bbox = me.bbox,
51676             i, shadow, shadows, attr;
51677
51678         sprite.shadows = shadows = [];
51679
51680         for (i = 0; i < lnsh; i++) {
51681             attr = Ext.apply({}, shadowAttributes[i]);
51682             if (attr.translate) {
51683                 attr.translate.x += (bbox.x + bbox.width) / 2;
51684                 attr.translate.y += (bbox.y + bbox.height) / 2;
51685             }
51686             else {
51687                 Ext.apply(attr, {
51688                     translate: {
51689                         x: (bbox.x + bbox.width) / 2,
51690                         y: (bbox.y + bbox.height) / 2
51691                     }
51692                 });
51693             }
51694             Ext.apply(attr, endMarkerStyle);
51695             shadow = Ext.chart.Shape[type](chart.surface, Ext.apply({}, {
51696                 x: 0,
51697                 y: 0,
51698                 group: shadowGroups[i]
51699             }, attr));
51700             shadows.push(shadow);
51701         }
51702     },
51703
51704     
51705     drawSeries: function() {
51706         var me = this,
51707             chart = me.chart,
51708             store = chart.getChartStore(),
51709             group = me.group,
51710             enableShadows = chart.shadow,
51711             shadowGroups = me.shadowGroups,
51712             shadowAttributes = me.shadowAttributes,
51713             lnsh = shadowGroups.length,
51714             sprite, attrs, attr, ln, i, endMarkerStyle, shindex, type, shadows,
51715             rendererAttributes, shadowAttribute;
51716
51717         endMarkerStyle = Ext.apply(me.markerStyle, me.markerConfig);
51718         type = endMarkerStyle.type;
51719         delete endMarkerStyle.type;
51720
51721         
51722         if (!store || !store.getCount()) {
51723             return;
51724         }
51725
51726         me.unHighlightItem();
51727         me.cleanHighlights();
51728
51729         attrs = me.getPaths();
51730         ln = attrs.length;
51731         for (i = 0; i < ln; i++) {
51732             attr = attrs[i];
51733             sprite = group.getAt(i);
51734             Ext.apply(attr, endMarkerStyle);
51735
51736             
51737             if (!sprite) {
51738                 sprite = me.createPoint(attr, type);
51739                 if (enableShadows) {
51740                     me.createShadow(sprite, endMarkerStyle, type);
51741                 }
51742             }
51743
51744             shadows = sprite.shadows;
51745             if (chart.animate) {
51746                 rendererAttributes = me.renderer(sprite, store.getAt(i), { translate: attr }, i, store);
51747                 sprite._to = rendererAttributes;
51748                 me.onAnimate(sprite, {
51749                     to: rendererAttributes
51750                 });
51751                 
51752                 for (shindex = 0; shindex < lnsh; shindex++) {
51753                     shadowAttribute = Ext.apply({}, shadowAttributes[shindex]);
51754                     rendererAttributes = me.renderer(shadows[shindex], store.getAt(i), Ext.apply({}, { 
51755                         hidden: false,
51756                         translate: {
51757                             x: attr.x + (shadowAttribute.translate? shadowAttribute.translate.x : 0),
51758                             y: attr.y + (shadowAttribute.translate? shadowAttribute.translate.y : 0)
51759                         }
51760                     }, shadowAttribute), i, store);
51761                     me.onAnimate(shadows[shindex], { to: rendererAttributes });
51762                 }
51763             }
51764             else {
51765                 rendererAttributes = me.renderer(sprite, store.getAt(i), { translate: attr }, i, store);
51766                 sprite._to = rendererAttributes;
51767                 sprite.setAttributes(rendererAttributes, true);
51768                 
51769                 for (shindex = 0; shindex < lnsh; shindex++) {
51770                     shadowAttribute = Ext.apply({}, shadowAttributes[shindex]);
51771                     rendererAttributes = me.renderer(shadows[shindex], store.getAt(i), Ext.apply({}, { 
51772                         hidden: false,
51773                         translate: {
51774                             x: attr.x + (shadowAttribute.translate? shadowAttribute.translate.x : 0),
51775                             y: attr.y + (shadowAttribute.translate? shadowAttribute.translate.y : 0)
51776                         } 
51777                     }, shadowAttribute), i, store);
51778                     shadows[shindex].setAttributes(rendererAttributes, true);
51779                 }
51780             }
51781             me.items[i].sprite = sprite;
51782         }
51783
51784         
51785         ln = group.getCount();
51786         for (i = attrs.length; i < ln; i++) {
51787             group.getAt(i).hide(true);
51788         }
51789         me.renderLabels();
51790         me.renderCallouts();
51791     },
51792
51793     
51794     onCreateLabel: function(storeItem, item, i, display) {
51795         var me = this,
51796             group = me.labelsGroup,
51797             config = me.label,
51798             endLabelStyle = Ext.apply({}, config, me.seriesLabelStyle),
51799             bbox = me.bbox;
51800
51801         return me.chart.surface.add(Ext.apply({
51802             type: 'text',
51803             group: group,
51804             x: item.point[0],
51805             y: bbox.y + bbox.height / 2
51806         }, endLabelStyle));
51807     },
51808
51809     
51810     onPlaceLabel: function(label, storeItem, item, i, display, animate) {
51811         var me = this,
51812             chart = me.chart,
51813             resizing = chart.resizing,
51814             config = me.label,
51815             format = config.renderer,
51816             field = config.field,
51817             bbox = me.bbox,
51818             x = item.point[0],
51819             y = item.point[1],
51820             radius = item.sprite.attr.radius,
51821             bb, width, height, anim;
51822
51823         label.setAttributes({
51824             text: format(storeItem.get(field)),
51825             hidden: true
51826         }, true);
51827
51828         if (display == 'rotate') {
51829             label.setAttributes({
51830                 'text-anchor': 'start',
51831                 'rotation': {
51832                     x: x,
51833                     y: y,
51834                     degrees: -45
51835                 }
51836             }, true);
51837             
51838             bb = label.getBBox();
51839             width = bb.width;
51840             height = bb.height;
51841             x = x < bbox.x? bbox.x : x;
51842             x = (x + width > bbox.x + bbox.width)? (x - (x + width - bbox.x - bbox.width)) : x;
51843             y = (y - height < bbox.y)? bbox.y + height : y;
51844
51845         } else if (display == 'under' || display == 'over') {
51846             
51847             bb = item.sprite.getBBox();
51848             bb.width = bb.width || (radius * 2);
51849             bb.height = bb.height || (radius * 2);
51850             y = y + (display == 'over'? -bb.height : bb.height);
51851             
51852             bb = label.getBBox();
51853             width = bb.width/2;
51854             height = bb.height/2;
51855             x = x - width < bbox.x ? bbox.x + width : x;
51856             x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
51857             y = y - height < bbox.y? bbox.y + height : y;
51858             y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
51859         }
51860
51861         if (!chart.animate) {
51862             label.setAttributes({
51863                 x: x,
51864                 y: y
51865             }, true);
51866             label.show(true);
51867         }
51868         else {
51869             if (resizing) {
51870                 anim = item.sprite.getActiveAnimation();
51871                 if (anim) {
51872                     anim.on('afteranimate', function() {
51873                         label.setAttributes({
51874                             x: x,
51875                             y: y
51876                         }, true);
51877                         label.show(true);
51878                     });
51879                 }
51880                 else {
51881                     label.show(true);
51882                 }
51883             }
51884             else {
51885                 me.onAnimate(label, {
51886                     to: {
51887                         x: x,
51888                         y: y
51889                     }
51890                 });
51891             }
51892         }
51893     },
51894
51895     
51896     onPlaceCallout: function(callout, storeItem, item, i, display, animate, index) {
51897         var me = this,
51898             chart = me.chart,
51899             surface = chart.surface,
51900             resizing = chart.resizing,
51901             config = me.callouts,
51902             items = me.items,
51903             cur = item.point,
51904             normal,
51905             bbox = callout.label.getBBox(),
51906             offsetFromViz = 30,
51907             offsetToSide = 10,
51908             offsetBox = 3,
51909             boxx, boxy, boxw, boxh,
51910             p, clipRect = me.bbox,
51911             x, y;
51912
51913         
51914         normal = [Math.cos(Math.PI /4), -Math.sin(Math.PI /4)];
51915         x = cur[0] + normal[0] * offsetFromViz;
51916         y = cur[1] + normal[1] * offsetFromViz;
51917
51918         
51919         boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
51920         boxy = y - bbox.height /2 - offsetBox;
51921         boxw = bbox.width + 2 * offsetBox;
51922         boxh = bbox.height + 2 * offsetBox;
51923
51924         
51925         
51926         if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) {
51927             normal[0] *= -1;
51928         }
51929         if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) {
51930             normal[1] *= -1;
51931         }
51932
51933         
51934         x = cur[0] + normal[0] * offsetFromViz;
51935         y = cur[1] + normal[1] * offsetFromViz;
51936
51937         
51938         boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
51939         boxy = y - bbox.height /2 - offsetBox;
51940         boxw = bbox.width + 2 * offsetBox;
51941         boxh = bbox.height + 2 * offsetBox;
51942
51943         if (chart.animate) {
51944             
51945             me.onAnimate(callout.lines, {
51946                 to: {
51947                     path: ["M", cur[0], cur[1], "L", x, y, "Z"]
51948                 }
51949             }, true);
51950             
51951             me.onAnimate(callout.box, {
51952                 to: {
51953                     x: boxx,
51954                     y: boxy,
51955                     width: boxw,
51956                     height: boxh
51957                 }
51958             }, true);
51959             
51960             me.onAnimate(callout.label, {
51961                 to: {
51962                     x: x + (normal[0] > 0? offsetBox : -(bbox.width + offsetBox)),
51963                     y: y
51964                 }
51965             }, true);
51966         } else {
51967             
51968             callout.lines.setAttributes({
51969                 path: ["M", cur[0], cur[1], "L", x, y, "Z"]
51970             }, true);
51971             
51972             callout.box.setAttributes({
51973                 x: boxx,
51974                 y: boxy,
51975                 width: boxw,
51976                 height: boxh
51977             }, true);
51978             
51979             callout.label.setAttributes({
51980                 x: x + (normal[0] > 0? offsetBox : -(bbox.width + offsetBox)),
51981                 y: y
51982             }, true);
51983         }
51984         for (p in callout) {
51985             callout[p].show(true);
51986         }
51987     },
51988
51989     
51990     onAnimate: function(sprite, attr) {
51991         sprite.show();
51992         return this.callParent(arguments);
51993     },
51994
51995     isItemInPoint: function(x, y, item) {
51996         var point,
51997             tolerance = 10,
51998             abs = Math.abs;
51999
52000         function dist(point) {
52001             var dx = abs(point[0] - x),
52002                 dy = abs(point[1] - y);
52003             return Math.sqrt(dx * dx + dy * dy);
52004         }
52005         point = item.point;
52006         return (point[0] - tolerance <= x && point[0] + tolerance >= x &&
52007             point[1] - tolerance <= y && point[1] + tolerance >= y);
52008     }
52009 });
52010
52011
52012
52013 Ext.define('Ext.chart.theme.Base', {
52014
52015     
52016
52017     requires: ['Ext.chart.theme.Theme'],
52018
52019     
52020
52021     constructor: function(config) {
52022         Ext.chart.theme.call(this, config, {
52023             background: false,
52024             axis: {
52025                 stroke: '#444',
52026                 'stroke-width': 1
52027             },
52028             axisLabelTop: {
52029                 fill: '#444',
52030                 font: '12px Arial, Helvetica, sans-serif',
52031                 spacing: 2,
52032                 padding: 5,
52033                 renderer: function(v) { return v; }
52034             },
52035             axisLabelRight: {
52036                 fill: '#444',
52037                 font: '12px Arial, Helvetica, sans-serif',
52038                 spacing: 2,
52039                 padding: 5,
52040                 renderer: function(v) { return v; }
52041             },
52042             axisLabelBottom: {
52043                 fill: '#444',
52044                 font: '12px Arial, Helvetica, sans-serif',
52045                 spacing: 2,
52046                 padding: 5,
52047                 renderer: function(v) { return v; }
52048             },
52049             axisLabelLeft: {
52050                 fill: '#444',
52051                 font: '12px Arial, Helvetica, sans-serif',
52052                 spacing: 2,
52053                 padding: 5,
52054                 renderer: function(v) { return v; }
52055             },
52056             axisTitleTop: {
52057                 font: 'bold 18px Arial',
52058                 fill: '#444'
52059             },
52060             axisTitleRight: {
52061                 font: 'bold 18px Arial',
52062                 fill: '#444',
52063                 rotate: {
52064                     x:0, y:0,
52065                     degrees: 270
52066                 }
52067             },
52068             axisTitleBottom: {
52069                 font: 'bold 18px Arial',
52070                 fill: '#444'
52071             },
52072             axisTitleLeft: {
52073                 font: 'bold 18px Arial',
52074                 fill: '#444',
52075                 rotate: {
52076                     x:0, y:0,
52077                     degrees: 270
52078                 }
52079             },
52080             series: {
52081                 'stroke-width': 0
52082             },
52083             seriesLabel: {
52084                 font: '12px Arial',
52085                 fill: '#333'
52086             },
52087             marker: {
52088                 stroke: '#555',
52089                 fill: '#000',
52090                 radius: 3,
52091                 size: 3
52092             },
52093             colors: [ "#94ae0a", "#115fa6","#a61120", "#ff8809", "#ffd13e", "#a61187", "#24ad9a", "#7c7474", "#a66111"],
52094             seriesThemes: [{
52095                 fill: "#115fa6"
52096             }, {
52097                 fill: "#94ae0a"
52098             }, {
52099                 fill: "#a61120"
52100             }, {
52101                 fill: "#ff8809"
52102             }, {
52103                 fill: "#ffd13e"
52104             }, {
52105                 fill: "#a61187"
52106             }, {
52107                 fill: "#24ad9a"
52108             }, {
52109                 fill: "#7c7474"
52110             }, {
52111                 fill: "#a66111"
52112             }],
52113             markerThemes: [{
52114                 fill: "#115fa6",
52115                 type: 'circle' 
52116             }, {
52117                 fill: "#94ae0a",
52118                 type: 'cross'
52119             }, {
52120                 fill: "#a61120",
52121                 type: 'plus'
52122             }]
52123         });
52124     }
52125 }, function() {
52126     var palette = ['#b1da5a', '#4ce0e7', '#e84b67', '#da5abd', '#4d7fe6', '#fec935'],
52127         names = ['Green', 'Sky', 'Red', 'Purple', 'Blue', 'Yellow'],
52128         i = 0, j = 0, l = palette.length, themes = Ext.chart.theme,
52129         categories = [['#f0a50a', '#c20024', '#2044ba', '#810065', '#7eae29'],
52130                       ['#6d9824', '#87146e', '#2a9196', '#d39006', '#1e40ac'],
52131                       ['#fbbc29', '#ce2e4e', '#7e0062', '#158b90', '#57880e'],
52132                       ['#ef5773', '#fcbd2a', '#4f770d', '#1d3eaa', '#9b001f'],
52133                       ['#7eae29', '#fdbe2a', '#910019', '#27b4bc', '#d74dbc'],
52134                       ['#44dce1', '#0b2592', '#996e05', '#7fb325', '#b821a1']],
52135         cats = categories.length;
52136     
52137     
52138     for (; i < l; i++) {
52139         themes[names[i]] = (function(color) {
52140             return Ext.extend(themes.Base, {
52141                 constructor: function(config) {
52142                     themes.Base.prototype.constructor.call(this, Ext.apply({
52143                         baseColor: color
52144                     }, config));
52145                 }
52146             });
52147         })(palette[i]);
52148     }
52149     
52150     
52151     for (i = 0; i < cats; i++) {
52152         themes['Category' + (i + 1)] = (function(category) {
52153             return Ext.extend(themes.Base, {
52154                 constructor: function(config) {
52155                     themes.Base.prototype.constructor.call(this, Ext.apply({
52156                         colors: category
52157                     }, config));
52158                 }
52159             });
52160         })(categories[i]);
52161     }
52162 });
52163
52164
52165 Ext.define('Ext.data.ArrayStore', {
52166     extend: 'Ext.data.Store',
52167     alias: 'store.array',
52168     uses: ['Ext.data.reader.Array'],
52169
52170     constructor: function(config) {
52171         config = config || {};
52172
52173         Ext.applyIf(config, {
52174             proxy: {
52175                 type: 'memory',
52176                 reader: 'array'
52177             }
52178         });
52179
52180         this.callParent([config]);
52181     },
52182
52183     loadData: function(data, append) {
52184         if (this.expandData === true) {
52185             var r = [],
52186                 i = 0,
52187                 ln = data.length;
52188
52189             for (; i < ln; i++) {
52190                 r[r.length] = [data[i]];
52191             }
52192
52193             data = r;
52194         }
52195
52196         this.callParent([data, append]);
52197     }
52198 }, function() {
52199     
52200     Ext.data.SimpleStore = Ext.data.ArrayStore;
52201     
52202 });
52203
52204
52205 Ext.define('Ext.data.Batch', {
52206     mixins: {
52207         observable: 'Ext.util.Observable'
52208     },
52209
52210     
52211     autoStart: false,
52212
52213     
52214     current: -1,
52215
52216     
52217     total: 0,
52218
52219     
52220     isRunning: false,
52221
52222     
52223     isComplete: false,
52224
52225     
52226     hasException: false,
52227
52228     
52229     pauseOnException: true,
52230
52231     
52232     constructor: function(config) {
52233         var me = this;
52234
52235         me.addEvents(
52236           
52237           'complete',
52238
52239           
52240           'exception',
52241
52242           
52243           'operationcomplete'
52244         );
52245
52246         me.mixins.observable.constructor.call(me, config);
52247
52248         
52249         me.operations = [];
52250     },
52251
52252     
52253     add: function(operation) {
52254         this.total++;
52255
52256         operation.setBatch(this);
52257
52258         this.operations.push(operation);
52259     },
52260
52261     
52262     start: function() {
52263         this.hasException = false;
52264         this.isRunning = true;
52265
52266         this.runNextOperation();
52267     },
52268
52269     
52270     runNextOperation: function() {
52271         this.runOperation(this.current + 1);
52272     },
52273
52274     
52275     pause: function() {
52276         this.isRunning = false;
52277     },
52278
52279     
52280     runOperation: function(index) {
52281         var me = this,
52282             operations = me.operations,
52283             operation  = operations[index],
52284             onProxyReturn;
52285
52286         if (operation === undefined) {
52287             me.isRunning  = false;
52288             me.isComplete = true;
52289             me.fireEvent('complete', me, operations[operations.length - 1]);
52290         } else {
52291             me.current = index;
52292
52293             onProxyReturn = function(operation) {
52294                 var hasException = operation.hasException();
52295
52296                 if (hasException) {
52297                     me.hasException = true;
52298                     me.fireEvent('exception', me, operation);
52299                 } else {
52300                     me.fireEvent('operationcomplete', me, operation);
52301                 }
52302
52303                 if (hasException && me.pauseOnException) {
52304                     me.pause();
52305                 } else {
52306                     operation.setCompleted();
52307                     me.runNextOperation();
52308                 }
52309             };
52310
52311             operation.setStarted();
52312
52313             me.proxy[operation.action](operation, onProxyReturn, me);
52314         }
52315     }
52316 });
52317
52318 Ext.define('Ext.data.BelongsToAssociation', {
52319     extend: 'Ext.data.Association',
52320
52321     alias: 'association.belongsto',
52322
52323     
52324
52325     
52326
52327     
52328
52329     
52330     constructor: function(config) {
52331         this.callParent(arguments);
52332
52333         var me             = this,
52334             ownerProto     = me.ownerModel.prototype,
52335             associatedName = me.associatedName,
52336             getterName     = me.getterName || 'get' + associatedName,
52337             setterName     = me.setterName || 'set' + associatedName;
52338
52339         Ext.applyIf(me, {
52340             name        : associatedName,
52341             foreignKey  : associatedName.toLowerCase() + "_id",
52342             instanceName: associatedName + 'BelongsToInstance',
52343             associationKey: associatedName.toLowerCase()
52344         });
52345
52346         ownerProto[getterName] = me.createGetter();
52347         ownerProto[setterName] = me.createSetter();
52348     },
52349
52350     
52351     createSetter: function() {
52352         var me              = this,
52353             ownerModel      = me.ownerModel,
52354             associatedModel = me.associatedModel,
52355             foreignKey      = me.foreignKey,
52356             primaryKey      = me.primaryKey;
52357
52358         
52359         return function(value, options, scope) {
52360             this.set(foreignKey, value);
52361
52362             if (typeof options == 'function') {
52363                 options = {
52364                     callback: options,
52365                     scope: scope || this
52366                 };
52367             }
52368
52369             if (Ext.isObject(options)) {
52370                 return this.save(options);
52371             }
52372         };
52373     },
52374
52375     
52376     createGetter: function() {
52377         var me              = this,
52378             ownerModel      = me.ownerModel,
52379             associatedName  = me.associatedName,
52380             associatedModel = me.associatedModel,
52381             foreignKey      = me.foreignKey,
52382             primaryKey      = me.primaryKey,
52383             instanceName    = me.instanceName;
52384
52385         
52386         return function(options, scope) {
52387             options = options || {};
52388
52389             var model = this,
52390                 foreignKeyId = model.get(foreignKey),
52391                 instance,
52392                 args;
52393
52394             if (model[instanceName] === undefined) {
52395                 instance = Ext.ModelManager.create({}, associatedName);
52396                 instance.set(primaryKey, foreignKeyId);
52397
52398                 if (typeof options == 'function') {
52399                     options = {
52400                         callback: options,
52401                         scope: scope || model
52402                     };
52403                 }
52404
52405                 associatedModel.load(foreignKeyId, options);
52406                 model[instanceName] = associatedModel;
52407                 return associatedModel;
52408             } else {
52409                 instance = model[instanceName];
52410                 args = [instance];
52411                 scope = scope || model;
52412
52413                 
52414                 
52415                 
52416                 Ext.callback(options, scope, args);
52417                 Ext.callback(options.success, scope, args);
52418                 Ext.callback(options.failure, scope, args);
52419                 Ext.callback(options.callback, scope, args);
52420
52421                 return instance;
52422             }
52423         };
52424     },
52425
52426     
52427     read: function(record, reader, associationData){
52428         record[this.instanceName] = reader.read([associationData]).records[0];
52429     }
52430 });
52431
52432
52433 Ext.define('Ext.data.BufferStore', {
52434     extend: 'Ext.data.Store',
52435     alias: 'store.buffer',
52436     sortOnLoad: false,
52437     filterOnLoad: false,
52438     
52439     constructor: function() {
52440         Ext.Error.raise('The BufferStore class has been deprecated. Instead, specify the buffered config option on Ext.data.Store');
52441     }
52442 });
52443
52444 Ext.define('Ext.direct.Manager', {
52445
52446     
52447     singleton: true,
52448
52449     mixins: {
52450         observable: 'Ext.util.Observable'
52451     },
52452
52453     requires: ['Ext.util.MixedCollection'],
52454
52455     statics: {
52456         exceptions: {
52457             TRANSPORT: 'xhr',
52458             PARSE: 'parse',
52459             LOGIN: 'login',
52460             SERVER: 'exception'
52461         }
52462     },
52463
52464     
52465
52466     constructor: function(){
52467         var me = this;
52468
52469         me.addEvents(
52470             
52471             'event',
52472             
52473             'exception'
52474         );
52475         me.transactions = Ext.create('Ext.util.MixedCollection');
52476         me.providers = Ext.create('Ext.util.MixedCollection');
52477
52478         me.mixins.observable.constructor.call(me);
52479     },
52480
52481     
52482     addProvider : function(provider){
52483         var me = this,
52484             args = arguments,
52485             i = 0,
52486             len;
52487
52488         if (args.length > 1) {
52489             for (len = args.length; i < len; ++i) {
52490                 me.addProvider(args[i]);
52491             }
52492             return;
52493         }
52494
52495         
52496         if (!provider.isProvider) {
52497             provider = Ext.create('direct.' + provider.type + 'provider', provider);
52498         }
52499         me.providers.add(provider);
52500         provider.on('data', me.onProviderData, me);
52501
52502
52503         if (!provider.isConnected()) {
52504             provider.connect();
52505         }
52506
52507         return provider;
52508     },
52509
52510     
52511     getProvider : function(id){
52512         return id.isProvider ? id : this.providers.get(id);
52513     },
52514
52515     
52516     removeProvider : function(provider){
52517         var me = this,
52518             providers = me.providers;
52519
52520         provider = provider.isProvider ? provider : providers.get(provider);
52521
52522         if (provider) {
52523             provider.un('data', me.onProviderData, me);
52524             providers.remove(provider);
52525             return provider;
52526         }
52527         return null;
52528     },
52529
52530     
52531     addTransaction: function(transaction){
52532         this.transactions.add(transaction);
52533         return transaction;
52534     },
52535
52536     
52537     removeTransaction: function(transaction){
52538         transaction = this.getTransaction(transaction);
52539         this.transactions.remove(transaction);
52540         return transaction;
52541     },
52542
52543     
52544     getTransaction: function(transaction){
52545         return transaction.isTransaction ? transaction : this.transactions.get(transaction);
52546     },
52547
52548     onProviderData : function(provider, event){
52549         var me = this,
52550             i = 0,
52551             len;
52552
52553         if (Ext.isArray(event)) {
52554             for (len = event.length; i < len; ++i) {
52555                 me.onProviderData(provider, event[i]);
52556             }
52557             return;
52558         }
52559         if (event.name && event.name != 'event' && event.name != 'exception') {
52560             me.fireEvent(event.name, event);
52561         } else if (event.status === false) {
52562             me.fireEvent('exception', event);
52563         }
52564         me.fireEvent('event', event, provider);
52565     }
52566 }, function(){
52567     
52568     Ext.Direct = Ext.direct.Manager;
52569 });
52570
52571
52572 Ext.define('Ext.data.proxy.Direct', {
52573     
52574
52575     extend: 'Ext.data.proxy.Server',
52576     alternateClassName: 'Ext.data.DirectProxy',
52577
52578     alias: 'proxy.direct',
52579
52580     requires: ['Ext.direct.Manager'],
52581
52582     
52583
52584     
52585     paramOrder: undefined,
52586
52587     
52588     paramsAsHash: true,
52589
52590     
52591     directFn : undefined,
52592
52593     
52594
52595     
52596
52597     
52598     paramOrderRe: /[\s,|]/,
52599
52600     constructor: function(config){
52601         var me = this;
52602
52603         Ext.apply(me, config);
52604         if (Ext.isString(me.paramOrder)) {
52605             me.paramOrder = me.paramOrder.split(me.paramOrderRe);
52606         }
52607         me.callParent(arguments);
52608     },
52609
52610     doRequest: function(operation, callback, scope) {
52611         var me = this,
52612             writer = me.getWriter(),
52613             request = me.buildRequest(operation, callback, scope),
52614             fn = me.api[request.action]  || me.directFn,
52615             args = [],
52616             params = request.params,
52617             paramOrder = me.paramOrder,
52618             method,
52619             i = 0,
52620             len;
52621
52622
52623         if (operation.allowWrite()) {
52624             request = writer.write(request);
52625         }
52626
52627         if (operation.action == 'read') {
52628             
52629             method = fn.directCfg.method;
52630
52631             if (method.ordered) {
52632                 if (method.len > 0) {
52633                     if (paramOrder) {
52634                         for (len = paramOrder.length; i < len; ++i) {
52635                             args.push(params[paramOrder[i]]);
52636                         }
52637                     } else if (me.paramsAsHash) {
52638                         args.push(params);
52639                     }
52640                 }
52641             } else {
52642                 args.push(params);
52643             }
52644         } else {
52645             args.push(request.jsonData);
52646         }
52647
52648         Ext.apply(request, {
52649             args: args,
52650             directFn: fn
52651         });
52652         args.push(me.createRequestCallback(request, operation, callback, scope), me);
52653         fn.apply(window, args);
52654     },
52655
52656     
52657     applyEncoding: function(value){
52658         return value;
52659     },
52660
52661     createRequestCallback: function(request, operation, callback, scope){
52662         var me = this;
52663
52664         return function(data, event){
52665             me.processResponse(event.status, operation, request, event, callback, scope);
52666         };
52667     },
52668
52669     
52670     extractResponseData: function(response){
52671         return Ext.isDefined(response.result) ? response.result : response.data;
52672     },
52673
52674     
52675     setException: function(operation, response) {
52676         operation.setException(response.message);
52677     },
52678
52679     
52680     buildUrl: function(){
52681         return '';
52682     }
52683 });
52684
52685
52686 Ext.define('Ext.data.DirectStore', {
52687     
52688     
52689     extend: 'Ext.data.Store',
52690     
52691     alias: 'store.direct',
52692     
52693     requires: ['Ext.data.proxy.Direct'],
52694    
52695     
52696
52697     constructor : function(config){
52698         config = Ext.apply({}, config);
52699         if (!config.proxy) {
52700             var proxy = {
52701                 type: 'direct',
52702                 reader: {
52703                     type: 'json'
52704                 }
52705             };
52706             Ext.copyTo(proxy, config, 'paramOrder,paramsAsHash,directFn,api,simpleSortMode');
52707             Ext.copyTo(proxy.reader, config, 'totalProperty,root,idProperty');
52708             config.proxy = proxy;
52709         }
52710         this.callParent([config]);
52711     }    
52712 });
52713
52714
52715 Ext.define('Ext.util.Inflector', {
52716
52717     
52718
52719     singleton: true,
52720
52721     
52722
52723     
52724     plurals: [
52725         [(/(quiz)$/i),                "$1zes"  ],
52726         [(/^(ox)$/i),                 "$1en"   ],
52727         [(/([m|l])ouse$/i),           "$1ice"  ],
52728         [(/(matr|vert|ind)ix|ex$/i),  "$1ices" ],
52729         [(/(x|ch|ss|sh)$/i),          "$1es"   ],
52730         [(/([^aeiouy]|qu)y$/i),       "$1ies"  ],
52731         [(/(hive)$/i),                "$1s"    ],
52732         [(/(?:([^f])fe|([lr])f)$/i),  "$1$2ves"],
52733         [(/sis$/i),                   "ses"    ],
52734         [(/([ti])um$/i),              "$1a"    ],
52735         [(/(buffal|tomat|potat)o$/i), "$1oes"  ],
52736         [(/(bu)s$/i),                 "$1ses"  ],
52737         [(/(alias|status|sex)$/i),    "$1es"   ],
52738         [(/(octop|vir)us$/i),         "$1i"    ],
52739         [(/(ax|test)is$/i),           "$1es"   ],
52740         [(/^person$/),                "people" ],
52741         [(/^man$/),                   "men"    ],
52742         [(/^(child)$/),               "$1ren"  ],
52743         [(/s$/i),                     "s"      ],
52744         [(/$/),                       "s"      ]
52745     ],
52746
52747     
52748     singulars: [
52749       [(/(quiz)zes$/i),                                                    "$1"     ],
52750       [(/(matr)ices$/i),                                                   "$1ix"   ],
52751       [(/(vert|ind)ices$/i),                                               "$1ex"   ],
52752       [(/^(ox)en/i),                                                       "$1"     ],
52753       [(/(alias|status)es$/i),                                             "$1"     ],
52754       [(/(octop|vir)i$/i),                                                 "$1us"   ],
52755       [(/(cris|ax|test)es$/i),                                             "$1is"   ],
52756       [(/(shoe)s$/i),                                                      "$1"     ],
52757       [(/(o)es$/i),                                                        "$1"     ],
52758       [(/(bus)es$/i),                                                      "$1"     ],
52759       [(/([m|l])ice$/i),                                                   "$1ouse" ],
52760       [(/(x|ch|ss|sh)es$/i),                                               "$1"     ],
52761       [(/(m)ovies$/i),                                                     "$1ovie" ],
52762       [(/(s)eries$/i),                                                     "$1eries"],
52763       [(/([^aeiouy]|qu)ies$/i),                                            "$1y"    ],
52764       [(/([lr])ves$/i),                                                    "$1f"    ],
52765       [(/(tive)s$/i),                                                      "$1"     ],
52766       [(/(hive)s$/i),                                                      "$1"     ],
52767       [(/([^f])ves$/i),                                                    "$1fe"   ],
52768       [(/(^analy)ses$/i),                                                  "$1sis"  ],
52769       [(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i), "$1$2sis"],
52770       [(/([ti])a$/i),                                                      "$1um"   ],
52771       [(/(n)ews$/i),                                                       "$1ews"  ],
52772       [(/people$/i),                                                       "person" ],
52773       [(/s$/i),                                                            ""       ]
52774     ],
52775
52776     
52777      uncountable: [
52778         "sheep",
52779         "fish",
52780         "series",
52781         "species",
52782         "money",
52783         "rice",
52784         "information",
52785         "equipment",
52786         "grass",
52787         "mud",
52788         "offspring",
52789         "deer",
52790         "means"
52791     ],
52792
52793     
52794     singular: function(matcher, replacer) {
52795         this.singulars.unshift([matcher, replacer]);
52796     },
52797
52798     
52799     plural: function(matcher, replacer) {
52800         this.plurals.unshift([matcher, replacer]);
52801     },
52802
52803     
52804     clearSingulars: function() {
52805         this.singulars = [];
52806     },
52807
52808     
52809     clearPlurals: function() {
52810         this.plurals = [];
52811     },
52812
52813     
52814     isTransnumeral: function(word) {
52815         return Ext.Array.indexOf(this.uncountable, word) != -1;
52816     },
52817
52818     
52819     pluralize: function(word) {
52820         if (this.isTransnumeral(word)) {
52821             return word;
52822         }
52823
52824         var plurals = this.plurals,
52825             length  = plurals.length,
52826             tuple, regex, i;
52827
52828         for (i = 0; i < length; i++) {
52829             tuple = plurals[i];
52830             regex = tuple[0];
52831
52832             if (regex == word || (regex.test && regex.test(word))) {
52833                 return word.replace(regex, tuple[1]);
52834             }
52835         }
52836
52837         return word;
52838     },
52839
52840     
52841     singularize: function(word) {
52842         if (this.isTransnumeral(word)) {
52843             return word;
52844         }
52845
52846         var singulars = this.singulars,
52847             length    = singulars.length,
52848             tuple, regex, i;
52849
52850         for (i = 0; i < length; i++) {
52851             tuple = singulars[i];
52852             regex = tuple[0];
52853
52854             if (regex == word || (regex.test && regex.test(word))) {
52855                 return word.replace(regex, tuple[1]);
52856             }
52857         }
52858
52859         return word;
52860     },
52861
52862     
52863     classify: function(word) {
52864         return Ext.String.capitalize(this.singularize(word));
52865     },
52866
52867     
52868     ordinalize: function(number) {
52869         var parsed = parseInt(number, 10),
52870             mod10  = parsed % 10,
52871             mod100 = parsed % 100;
52872
52873         
52874         if (11 <= mod100 && mod100 <= 13) {
52875             return number + "th";
52876         } else {
52877             switch(mod10) {
52878                 case 1 : return number + "st";
52879                 case 2 : return number + "nd";
52880                 case 3 : return number + "rd";
52881                 default: return number + "th";
52882             }
52883         }
52884     }
52885 }, function() {
52886     
52887     var irregulars = {
52888             alumnus: 'alumni',
52889             cactus : 'cacti',
52890             focus  : 'foci',
52891             nucleus: 'nuclei',
52892             radius: 'radii',
52893             stimulus: 'stimuli',
52894             ellipsis: 'ellipses',
52895             paralysis: 'paralyses',
52896             oasis: 'oases',
52897             appendix: 'appendices',
52898             index: 'indexes',
52899             beau: 'beaux',
52900             bureau: 'bureaux',
52901             tableau: 'tableaux',
52902             woman: 'women',
52903             child: 'children',
52904             man: 'men',
52905             corpus:     'corpora',
52906             criterion: 'criteria',
52907             curriculum: 'curricula',
52908             genus: 'genera',
52909             memorandum: 'memoranda',
52910             phenomenon: 'phenomena',
52911             foot: 'feet',
52912             goose: 'geese',
52913             tooth: 'teeth',
52914             antenna: 'antennae',
52915             formula: 'formulae',
52916             nebula: 'nebulae',
52917             vertebra: 'vertebrae',
52918             vita: 'vitae'
52919         },
52920         singular;
52921
52922     for (singular in irregulars) {
52923         this.plural(singular, irregulars[singular]);
52924         this.singular(irregulars[singular], singular);
52925     }
52926 });
52927
52928 Ext.define('Ext.data.HasManyAssociation', {
52929     extend: 'Ext.data.Association',
52930     requires: ['Ext.util.Inflector'],
52931
52932     alias: 'association.hasmany',
52933
52934     
52935     
52936     
52937     
52938     
52939     
52940     
52941     
52942     
52943     
52944     
52945     
52946     constructor: function(config) {
52947         var me = this,
52948             ownerProto,
52949             name;
52950             
52951         me.callParent(arguments);
52952         
52953         me.name = me.name || Ext.util.Inflector.pluralize(me.associatedName.toLowerCase());
52954         
52955         ownerProto = me.ownerModel.prototype;
52956         name = me.name;
52957         
52958         Ext.applyIf(me, {
52959             storeName : name + "Store",
52960             foreignKey: me.ownerName.toLowerCase() + "_id"
52961         });
52962         
52963         ownerProto[name] = me.createStore();
52964     },
52965     
52966     
52967     createStore: function() {
52968         var that            = this,
52969             associatedModel = that.associatedModel,
52970             storeName       = that.storeName,
52971             foreignKey      = that.foreignKey,
52972             primaryKey      = that.primaryKey,
52973             filterProperty  = that.filterProperty,
52974             autoLoad        = that.autoLoad,
52975             storeConfig     = that.storeConfig || {};
52976         
52977         return function() {
52978             var me = this,
52979                 config, filter,
52980                 modelDefaults = {};
52981                 
52982             if (me[storeName] === undefined) {
52983                 if (filterProperty) {
52984                     filter = {
52985                         property  : filterProperty,
52986                         value     : me.get(filterProperty),
52987                         exactMatch: true
52988                     };
52989                 } else {
52990                     filter = {
52991                         property  : foreignKey,
52992                         value     : me.get(primaryKey),
52993                         exactMatch: true
52994                     };
52995                 }
52996                 
52997                 modelDefaults[foreignKey] = me.get(primaryKey);
52998                 
52999                 config = Ext.apply({}, storeConfig, {
53000                     model        : associatedModel,
53001                     filters      : [filter],
53002                     remoteFilter : false,
53003                     modelDefaults: modelDefaults
53004                 });
53005                 
53006                 me[storeName] = Ext.create('Ext.data.Store', config);
53007                 if (autoLoad) {
53008                     me[storeName].load();
53009                 }
53010             }
53011             
53012             return me[storeName];
53013         };
53014     },
53015     
53016     
53017     read: function(record, reader, associationData){
53018         var store = record[this.name](),
53019             inverse;
53020     
53021         store.add(reader.read(associationData).records);
53022     
53023         
53024         
53025         inverse = this.associatedModel.prototype.associations.findBy(function(assoc){
53026             return assoc.type === 'belongsTo' && assoc.associatedName === record.$className;
53027         });
53028     
53029         
53030         if (inverse) {
53031             store.data.each(function(associatedRecord){
53032                 associatedRecord[inverse.instanceName] = record;
53033             });
53034         }
53035     }
53036 });
53037
53038 Ext.define('Ext.data.JsonP', {
53039
53040     
53041
53042     singleton: true,
53043
53044     statics: {
53045         requestCount: 0,
53046         requests: {}
53047     },
53048
53049     
53050
53051     
53052     timeout: 30000,
53053
53054     
53055     disableCaching: true,
53056
53057     
53058     disableCachingParam: '_dc',
53059
53060     
53061     callbackKey: 'callback',
53062
53063     
53064     request: function(options){
53065         options = Ext.apply({}, options);
53066
53067
53068         var me = this,
53069             disableCaching = Ext.isDefined(options.disableCaching) ? options.disableCaching : me.disableCaching,
53070             cacheParam = options.disableCachingParam || me.disableCachingParam,
53071             id = ++me.statics().requestCount,
53072             callbackName = options.callbackName || 'callback' + id,
53073             callbackKey = options.callbackKey || me.callbackKey,
53074             timeout = Ext.isDefined(options.timeout) ? options.timeout : me.timeout,
53075             params = Ext.apply({}, options.params),
53076             url = options.url,
53077             name = Ext.isSandboxed ? Ext.getUniqueGlobalNamespace() : 'Ext',
53078             request,
53079             script;
53080
53081         params[callbackKey] = name + '.data.JsonP.' + callbackName;
53082         if (disableCaching) {
53083             params[cacheParam] = new Date().getTime();
53084         }
53085
53086         script = me.createScript(url, params);
53087
53088         me.statics().requests[id] = request = {
53089             url: url,
53090             params: params,
53091             script: script,
53092             id: id,
53093             scope: options.scope,
53094             success: options.success,
53095             failure: options.failure,
53096             callback: options.callback,
53097             callbackName: callbackName
53098         };
53099
53100         if (timeout > 0) {
53101             request.timeout = setTimeout(Ext.bind(me.handleTimeout, me, [request]), timeout);
53102         }
53103
53104         me.setupErrorHandling(request);
53105         me[callbackName] = Ext.bind(me.handleResponse, me, [request], true);
53106         Ext.getHead().appendChild(script);
53107         return request;
53108     },
53109
53110     
53111     abort: function(request){
53112         var requests = this.statics().requests,
53113             key;
53114
53115         if (request) {
53116             if (!request.id) {
53117                 request = requests[request];
53118             }
53119             this.abort(request);
53120         } else {
53121             for (key in requests) {
53122                 if (requests.hasOwnProperty(key)) {
53123                     this.abort(requests[key]);
53124                 }
53125             }
53126         }
53127     },
53128
53129     
53130     setupErrorHandling: function(request){
53131         request.script.onerror = Ext.bind(this.handleError, this, [request]);
53132     },
53133
53134     
53135     handleAbort: function(request){
53136         request.errorType = 'abort';
53137         this.handleResponse(null, request);
53138     },
53139
53140     
53141     handleError: function(request){
53142         request.errorType = 'error';
53143         this.handleResponse(null, request);
53144     },
53145
53146     
53147     cleanupErrorHandling: function(request){
53148         request.script.onerror = null;
53149     },
53150
53151     
53152     handleTimeout: function(request){
53153         request.errorType = 'timeout';
53154         this.handleResponse(null, request);
53155     },
53156
53157     
53158     handleResponse: function(result, request){
53159
53160         var success = true;
53161
53162         if (request.timeout) {
53163             clearTimeout(request.timeout);
53164         }
53165         delete this[request.callbackName];
53166         delete this.statics()[request.id];
53167         this.cleanupErrorHandling(request);
53168         Ext.fly(request.script).remove();
53169
53170         if (request.errorType) {
53171             success = false;
53172             Ext.callback(request.failure, request.scope, [request.errorType]);
53173         } else {
53174             Ext.callback(request.success, request.scope, [result]);
53175         }
53176         Ext.callback(request.callback, request.scope, [success, result, request.errorType]);
53177     },
53178
53179     
53180     createScript: function(url, params) {
53181         var script = document.createElement('script');
53182         script.setAttribute("src", Ext.urlAppend(url, Ext.Object.toQueryString(params)));
53183         script.setAttribute("async", true);
53184         script.setAttribute("type", "text/javascript");
53185         return script;
53186     }
53187 });
53188
53189
53190 Ext.define('Ext.data.JsonPStore', {
53191     extend: 'Ext.data.Store',
53192     alias : 'store.jsonp',
53193
53194     
53195     constructor: function(config) {
53196         this.callParent(Ext.apply(config, {
53197             reader: Ext.create('Ext.data.reader.Json', config),
53198             proxy : Ext.create('Ext.data.proxy.JsonP', config)
53199         }));
53200     }
53201 });
53202
53203
53204 Ext.define('Ext.data.NodeInterface', {
53205     requires: ['Ext.data.Field'],
53206
53207     
53208
53209     
53210
53211     
53212
53213     
53214
53215     
53216
53217     
53218
53219     
53220
53221     
53222
53223     
53224
53225     
53226
53227     
53228
53229     
53230
53231     
53232
53233     
53234
53235     
53236
53237     
53238
53239     
53240
53241     
53242
53243     
53244
53245     
53246
53247     
53248
53249     
53250
53251     
53252
53253
53254     
53255
53256     
53257
53258     
53259
53260     
53261
53262     
53263
53264     
53265
53266     statics: {
53267         
53268         decorate: function(record) {
53269             if (!record.isNode) {
53270                 
53271                 
53272                 var mgr = Ext.ModelManager,
53273                     modelName = record.modelName,
53274                     modelClass = mgr.getModel(modelName),
53275                     idName = modelClass.prototype.idProperty,
53276                     newFields = [],
53277                     i, newField, len;
53278
53279                 
53280                 modelClass.override(this.getPrototypeBody());
53281                 newFields = this.applyFields(modelClass, [
53282                     {name: idName,       type: 'string',  defaultValue: null},
53283                     {name: 'parentId',   type: 'string',  defaultValue: null},
53284                     {name: 'index',      type: 'int',     defaultValue: null},
53285                     {name: 'depth',      type: 'int',     defaultValue: 0},
53286                     {name: 'expanded',   type: 'bool',    defaultValue: false, persist: false},
53287                     {name: 'expandable', type: 'bool',    defaultValue: true, persist: false},
53288                     {name: 'checked',    type: 'auto',    defaultValue: null},
53289                     {name: 'leaf',       type: 'bool',    defaultValue: false, persist: false},
53290                     {name: 'cls',        type: 'string',  defaultValue: null, persist: false},
53291                     {name: 'iconCls',    type: 'string',  defaultValue: null, persist: false},
53292                     {name: 'icon',       type: 'string',  defaultValue: null, persist: false},
53293                     {name: 'root',       type: 'boolean', defaultValue: false, persist: false},
53294                     {name: 'isLast',     type: 'boolean', defaultValue: false, persist: false},
53295                     {name: 'isFirst',    type: 'boolean', defaultValue: false, persist: false},
53296                     {name: 'allowDrop',  type: 'boolean', defaultValue: true, persist: false},
53297                     {name: 'allowDrag',  type: 'boolean', defaultValue: true, persist: false},
53298                     {name: 'loaded',     type: 'boolean', defaultValue: false, persist: false},
53299                     {name: 'loading',    type: 'boolean', defaultValue: false, persist: false},
53300                     {name: 'href',       type: 'string',  defaultValue: null, persist: false},
53301                     {name: 'hrefTarget', type: 'string',  defaultValue: null, persist: false},
53302                     {name: 'qtip',       type: 'string',  defaultValue: null, persist: false},
53303                     {name: 'qtitle',     type: 'string',  defaultValue: null, persist: false}
53304                 ]);
53305
53306                 len = newFields.length;
53307                 
53308                 for (i = 0; i < len; ++i) {
53309                     newField = newFields[i];
53310                     if (record.get(newField.name) === undefined) {
53311                         record.data[newField.name] = newField.defaultValue;
53312                     }
53313                 }
53314             }
53315
53316             Ext.applyIf(record, {
53317                 firstChild: null,
53318                 lastChild: null,
53319                 parentNode: null,
53320                 previousSibling: null,
53321                 nextSibling: null,
53322                 childNodes: []
53323             });
53324             
53325             record.commit(true);
53326
53327             record.enableBubble([
53328                 
53329                 "append",
53330
53331                 
53332                 "remove",
53333
53334                 
53335                 "move",
53336
53337                 
53338                 "insert",
53339
53340                 
53341                 "beforeappend",
53342
53343                 
53344                 "beforeremove",
53345
53346                 
53347                 "beforemove",
53348
53349                  
53350                 "beforeinsert",
53351
53352                 
53353                 "expand",
53354
53355                 
53356                 "collapse",
53357
53358                 
53359                 "beforeexpand",
53360
53361                 
53362                 "beforecollapse",
53363
53364                 
53365                 "sort"
53366             ]);
53367
53368             return record;
53369         },
53370
53371         applyFields: function(modelClass, addFields) {
53372             var modelPrototype = modelClass.prototype,
53373                 fields = modelPrototype.fields,
53374                 keys = fields.keys,
53375                 ln = addFields.length,
53376                 addField, i, name,
53377                 newFields = [];
53378
53379             for (i = 0; i < ln; i++) {
53380                 addField = addFields[i];
53381                 if (!Ext.Array.contains(keys, addField.name)) {
53382                     addField = Ext.create('data.field', addField);
53383
53384                     newFields.push(addField);
53385                     fields.add(addField);
53386                 }
53387             }
53388
53389             return newFields;
53390         },
53391
53392         getPrototypeBody: function() {
53393             return {
53394                 isNode: true,
53395
53396                 
53397                 createNode: function(node) {
53398                     if (Ext.isObject(node) && !node.isModel) {
53399                         node = Ext.ModelManager.create(node, this.modelName);
53400                     }
53401                     
53402                     return Ext.data.NodeInterface.decorate(node);
53403                 },
53404
53405                 
53406                 isLeaf : function() {
53407                     return this.get('leaf') === true;
53408                 },
53409
53410                 
53411                 setFirstChild : function(node) {
53412                     this.firstChild = node;
53413                 },
53414
53415                 
53416                 setLastChild : function(node) {
53417                     this.lastChild = node;
53418                 },
53419
53420                 
53421                 updateInfo: function(silent) {
53422                     var me = this,
53423                         isRoot = me.isRoot(),
53424                         parentNode = me.parentNode,
53425                         isFirst = (!parentNode ? true : parentNode.firstChild == me),
53426                         isLast = (!parentNode ? true : parentNode.lastChild == me),
53427                         depth = 0,
53428                         parent = me,
53429                         children = me.childNodes,
53430                         len = children.length,
53431                         i = 0;
53432
53433                     while (parent.parentNode) {
53434                         ++depth;
53435                         parent = parent.parentNode;
53436                     }
53437
53438                     me.beginEdit();
53439                     me.set({
53440                         isFirst: isFirst,
53441                         isLast: isLast,
53442                         depth: depth,
53443                         index: parentNode ? parentNode.indexOf(me) : 0,
53444                         parentId: parentNode ? parentNode.getId() : null
53445                     });
53446                     me.endEdit(silent);
53447                     if (silent) {
53448                         me.commit();
53449                     }
53450
53451                     for (i = 0; i < len; i++) {
53452                         children[i].updateInfo(silent);
53453                     }
53454                 },
53455
53456                 
53457                 isLast : function() {
53458                    return this.get('isLast');
53459                 },
53460
53461                 
53462                 isFirst : function() {
53463                    return this.get('isFirst');
53464                 },
53465
53466                 
53467                 hasChildNodes : function() {
53468                     return !this.isLeaf() && this.childNodes.length > 0;
53469                 },
53470
53471                 
53472                 isExpandable : function() {
53473                     var me = this;
53474
53475                     if (me.get('expandable')) {
53476                         return !(me.isLeaf() || (me.isLoaded() && !me.hasChildNodes()));
53477                     }
53478                     return false;
53479                 },
53480
53481                 
53482                 appendChild : function(node, suppressEvents, suppressNodeUpdate) {
53483                     var me = this,
53484                         i, ln,
53485                         index,
53486                         oldParent,
53487                         ps;
53488
53489                     
53490                     if (Ext.isArray(node)) {
53491                         for (i = 0, ln = node.length; i < ln; i++) {
53492                             me.appendChild(node[i]);
53493                         }
53494                     } else {
53495                         
53496                         node = me.createNode(node);
53497
53498                         if (suppressEvents !== true && me.fireEvent("beforeappend", me, node) === false) {
53499                             return false;
53500                         }
53501
53502                         index = me.childNodes.length;
53503                         oldParent = node.parentNode;
53504
53505                         
53506                         if (oldParent) {
53507                             if (suppressEvents !== true && node.fireEvent("beforemove", node, oldParent, me, index) === false) {
53508                                 return false;
53509                             }
53510                             oldParent.removeChild(node, null, false, true);
53511                         }
53512
53513                         index = me.childNodes.length;
53514                         if (index === 0) {
53515                             me.setFirstChild(node);
53516                         }
53517
53518                         me.childNodes.push(node);
53519                         node.parentNode = me;
53520                         node.nextSibling = null;
53521
53522                         me.setLastChild(node);
53523
53524                         ps = me.childNodes[index - 1];
53525                         if (ps) {
53526                             node.previousSibling = ps;
53527                             ps.nextSibling = node;
53528                             ps.updateInfo(suppressNodeUpdate);
53529                         } else {
53530                             node.previousSibling = null;
53531                         }
53532
53533                         node.updateInfo(suppressNodeUpdate);
53534
53535                         
53536                         if (!me.isLoaded()) {
53537                             me.set('loaded', true);
53538                         }
53539                         
53540                         else if (me.childNodes.length === 1) {
53541                             me.set('loaded', me.isLoaded());
53542                         }
53543
53544                         if (suppressEvents !== true) {
53545                             me.fireEvent("append", me, node, index);
53546
53547                             if (oldParent) {
53548                                 node.fireEvent("move", node, oldParent, me, index);
53549                             }
53550                         }
53551
53552                         return node;
53553                     }
53554                 },
53555
53556                 
53557                 getBubbleTarget: function() {
53558                     return this.parentNode;
53559                 },
53560
53561                 
53562                 removeChild : function(node, destroy, suppressEvents, suppressNodeUpdate) {
53563                     var me = this,
53564                         index = me.indexOf(node);
53565
53566                     if (index == -1 || (suppressEvents !== true && me.fireEvent("beforeremove", me, node) === false)) {
53567                         return false;
53568                     }
53569
53570                     
53571                     Ext.Array.erase(me.childNodes, index, 1);
53572
53573                     
53574                     if (me.firstChild == node) {
53575                         me.setFirstChild(node.nextSibling);
53576                     }
53577                     if (me.lastChild == node) {
53578                         me.setLastChild(node.previousSibling);
53579                     }
53580
53581                     
53582                     if (node.previousSibling) {
53583                         node.previousSibling.nextSibling = node.nextSibling;
53584                         node.previousSibling.updateInfo(suppressNodeUpdate);
53585                     }
53586                     if (node.nextSibling) {
53587                         node.nextSibling.previousSibling = node.previousSibling;
53588                         node.nextSibling.updateInfo(suppressNodeUpdate);
53589                     }
53590
53591                     if (suppressEvents !== true) {
53592                         me.fireEvent("remove", me, node);
53593                     }
53594
53595
53596                     
53597                     if (!me.childNodes.length) {
53598                         me.set('loaded', me.isLoaded());
53599                     }
53600
53601                     if (destroy) {
53602                         node.destroy(true);
53603                     } else {
53604                         node.clear();
53605                     }
53606
53607                     return node;
53608                 },
53609
53610                 
53611                 copy: function(newId, deep) {
53612                     var me = this,
53613                         result = me.callOverridden(arguments),
53614                         len = me.childNodes ? me.childNodes.length : 0,
53615                         i;
53616
53617                     
53618                     if (deep) {
53619                         for (i = 0; i < len; i++) {
53620                             result.appendChild(me.childNodes[i].copy(true));
53621                         }
53622                     }
53623                     return result;
53624                 },
53625
53626                 
53627                 clear : function(destroy) {
53628                     var me = this;
53629
53630                     
53631                     me.parentNode = me.previousSibling = me.nextSibling = null;
53632                     if (destroy) {
53633                         me.firstChild = me.lastChild = null;
53634                     }
53635                 },
53636
53637                 
53638                 destroy : function(silent) {
53639                     
53640                     var me = this,
53641                         options = me.destroyOptions;
53642
53643                     if (silent === true) {
53644                         me.clear(true);
53645                         Ext.each(me.childNodes, function(n) {
53646                             n.destroy(true);
53647                         });
53648                         me.childNodes = null;
53649                         delete me.destroyOptions;
53650                         me.callOverridden([options]);
53651                     } else {
53652                         me.destroyOptions = silent;
53653                         
53654                         me.remove(true);
53655                     }
53656                 },
53657
53658                 
53659                 insertBefore : function(node, refNode, suppressEvents) {
53660                     var me = this,
53661                         index     = me.indexOf(refNode),
53662                         oldParent = node.parentNode,
53663                         refIndex  = index,
53664                         ps;
53665
53666                     if (!refNode) { 
53667                         return me.appendChild(node);
53668                     }
53669
53670                     
53671                     if (node == refNode) {
53672                         return false;
53673                     }
53674
53675                     
53676                     node = me.createNode(node);
53677
53678                     if (suppressEvents !== true && me.fireEvent("beforeinsert", me, node, refNode) === false) {
53679                         return false;
53680                     }
53681
53682                     
53683                     if (oldParent == me && me.indexOf(node) < index) {
53684                         refIndex--;
53685                     }
53686
53687                     
53688                     if (oldParent) {
53689                         if (suppressEvents !== true && node.fireEvent("beforemove", node, oldParent, me, index, refNode) === false) {
53690                             return false;
53691                         }
53692                         oldParent.removeChild(node);
53693                     }
53694
53695                     if (refIndex === 0) {
53696                         me.setFirstChild(node);
53697                     }
53698
53699                     Ext.Array.splice(me.childNodes, refIndex, 0, node);
53700                     node.parentNode = me;
53701
53702                     node.nextSibling = refNode;
53703                     refNode.previousSibling = node;
53704
53705                     ps = me.childNodes[refIndex - 1];
53706                     if (ps) {
53707                         node.previousSibling = ps;
53708                         ps.nextSibling = node;
53709                         ps.updateInfo();
53710                     } else {
53711                         node.previousSibling = null;
53712                     }
53713
53714                     node.updateInfo();
53715
53716                     if (!me.isLoaded()) {
53717                         me.set('loaded', true);
53718                     }
53719                     
53720                     else if (me.childNodes.length === 1) {
53721                         me.set('loaded', me.isLoaded());
53722                     }
53723
53724                     if (suppressEvents !== true) {
53725                         me.fireEvent("insert", me, node, refNode);
53726
53727                         if (oldParent) {
53728                             node.fireEvent("move", node, oldParent, me, refIndex, refNode);
53729                         }
53730                     }
53731
53732                     return node;
53733                 },
53734
53735                 
53736                 insertChild: function(index, node) {
53737                     var sibling = this.childNodes[index];
53738                     if (sibling) {
53739                         return this.insertBefore(node, sibling);
53740                     }
53741                     else {
53742                         return this.appendChild(node);
53743                     }
53744                 },
53745
53746                 
53747                 remove : function(destroy, suppressEvents) {
53748                     var parentNode = this.parentNode;
53749
53750                     if (parentNode) {
53751                         parentNode.removeChild(this, destroy, suppressEvents, true);
53752                     }
53753                     return this;
53754                 },
53755
53756                 
53757                 removeAll : function(destroy, suppressEvents) {
53758                     var cn = this.childNodes,
53759                         n;
53760
53761                     while ((n = cn[0])) {
53762                         this.removeChild(n, destroy, suppressEvents);
53763                     }
53764                     return this;
53765                 },
53766
53767                 
53768                 getChildAt : function(index) {
53769                     return this.childNodes[index];
53770                 },
53771
53772                 
53773                 replaceChild : function(newChild, oldChild, suppressEvents) {
53774                     var s = oldChild ? oldChild.nextSibling : null;
53775
53776                     this.removeChild(oldChild, suppressEvents);
53777                     this.insertBefore(newChild, s, suppressEvents);
53778                     return oldChild;
53779                 },
53780
53781                 
53782                 indexOf : function(child) {
53783                     return Ext.Array.indexOf(this.childNodes, child);
53784                 },
53785
53786                 
53787                 getPath: function(field, separator) {
53788                     field = field || this.idProperty;
53789                     separator = separator || '/';
53790
53791                     var path = [this.get(field)],
53792                         parent = this.parentNode;
53793
53794                     while (parent) {
53795                         path.unshift(parent.get(field));
53796                         parent = parent.parentNode;
53797                     }
53798                     return separator + path.join(separator);
53799                 },
53800
53801                 
53802                 getDepth : function() {
53803                     return this.get('depth');
53804                 },
53805
53806                 
53807                 bubble : function(fn, scope, args) {
53808                     var p = this;
53809                     while (p) {
53810                         if (fn.apply(scope || p, args || [p]) === false) {
53811                             break;
53812                         }
53813                         p = p.parentNode;
53814                     }
53815                 },
53816
53817                 cascade: function() {
53818                     if (Ext.isDefined(Ext.global.console)) {
53819                         Ext.global.console.warn('Ext.data.Node: cascade has been deprecated. Please use cascadeBy instead.');
53820                     }
53821                     return this.cascadeBy.apply(this, arguments);
53822                 },
53823
53824                 
53825                 cascadeBy : function(fn, scope, args) {
53826                     if (fn.apply(scope || this, args || [this]) !== false) {
53827                         var childNodes = this.childNodes,
53828                             length     = childNodes.length,
53829                             i;
53830
53831                         for (i = 0; i < length; i++) {
53832                             childNodes[i].cascadeBy(fn, scope, args);
53833                         }
53834                     }
53835                 },
53836
53837                 
53838                 eachChild : function(fn, scope, args) {
53839                     var childNodes = this.childNodes,
53840                         length     = childNodes.length,
53841                         i;
53842
53843                     for (i = 0; i < length; i++) {
53844                         if (fn.apply(scope || this, args || [childNodes[i]]) === false) {
53845                             break;
53846                         }
53847                     }
53848                 },
53849
53850                 
53851                 findChild : function(attribute, value, deep) {
53852                     return this.findChildBy(function() {
53853                         return this.get(attribute) == value;
53854                     }, null, deep);
53855                 },
53856
53857                 
53858                 findChildBy : function(fn, scope, deep) {
53859                     var cs = this.childNodes,
53860                         len = cs.length,
53861                         i = 0, n, res;
53862
53863                     for (; i < len; i++) {
53864                         n = cs[i];
53865                         if (fn.call(scope || n, n) === true) {
53866                             return n;
53867                         }
53868                         else if (deep) {
53869                             res = n.findChildBy(fn, scope, deep);
53870                             if (res !== null) {
53871                                 return res;
53872                             }
53873                         }
53874                     }
53875
53876                     return null;
53877                 },
53878
53879                 
53880                 contains : function(node) {
53881                     return node.isAncestor(this);
53882                 },
53883
53884                 
53885                 isAncestor : function(node) {
53886                     var p = this.parentNode;
53887                     while (p) {
53888                         if (p == node) {
53889                             return true;
53890                         }
53891                         p = p.parentNode;
53892                     }
53893                     return false;
53894                 },
53895
53896                 
53897                 sort : function(sortFn, recursive, suppressEvent) {
53898                     var cs  = this.childNodes,
53899                         ln = cs.length,
53900                         i, n;
53901
53902                     if (ln > 0) {
53903                         Ext.Array.sort(cs, sortFn);
53904                         for (i = 0; i < ln; i++) {
53905                             n = cs[i];
53906                             n.previousSibling = cs[i-1];
53907                             n.nextSibling = cs[i+1];
53908
53909                             if (i === 0) {
53910                                 this.setFirstChild(n);
53911                                 n.updateInfo();
53912                             }
53913                             if (i == ln - 1) {
53914                                 this.setLastChild(n);
53915                                 n.updateInfo();
53916                             }
53917                             if (recursive && !n.isLeaf()) {
53918                                 n.sort(sortFn, true, true);
53919                             }
53920                         }
53921
53922                         if (suppressEvent !== true) {
53923                             this.fireEvent('sort', this, cs);
53924                         }
53925                     }
53926                 },
53927
53928                 
53929                 isExpanded: function() {
53930                     return this.get('expanded');
53931                 },
53932
53933                 
53934                 isLoaded: function() {
53935                     return this.get('loaded');
53936                 },
53937
53938                 
53939                 isLoading: function() {
53940                     return this.get('loading');
53941                 },
53942
53943                 
53944                 isRoot: function() {
53945                     return !this.parentNode;
53946                 },
53947
53948                 
53949                 isVisible: function() {
53950                     var parent = this.parentNode;
53951                     while (parent) {
53952                         if (!parent.isExpanded()) {
53953                             return false;
53954                         }
53955                         parent = parent.parentNode;
53956                     }
53957                     return true;
53958                 },
53959
53960                 
53961                 expand: function(recursive, callback, scope) {
53962                     var me = this;
53963
53964                     
53965                     
53966
53967                     
53968                     if (!me.isLeaf()) {
53969                         
53970                         if (me.isLoading()) {
53971                             me.on('expand', function(){
53972                                 me.expand(recursive, callback, scope);
53973                             }, me, {single: true});
53974                         } else {
53975                             
53976                             if (!me.isExpanded()) {
53977                                 
53978                                 
53979                                 
53980                                 
53981                                 me.fireEvent('beforeexpand', me, function(){
53982                                     me.set('expanded', true);
53983                                     me.fireEvent('expand', me, me.childNodes, false);
53984
53985                                     
53986                                     if (recursive) {
53987                                         me.expandChildren(true, callback, scope);
53988                                     } else {
53989                                         Ext.callback(callback, scope || me, [me.childNodes]);
53990                                     }
53991                                 }, me);
53992                             } else if (recursive) {
53993                                 
53994                                 me.expandChildren(true, callback, scope);
53995                             } else {
53996                                 Ext.callback(callback, scope || me, [me.childNodes]);
53997                             }
53998                         }
53999                     } else {
54000                         
54001                         Ext.callback(callback, scope || me); 
54002                     }
54003                 },
54004
54005                 
54006                 expandChildren: function(recursive, callback, scope) {
54007                     var me = this,
54008                         i = 0,
54009                         nodes = me.childNodes,
54010                         ln = nodes.length,
54011                         node,
54012                         expanding = 0;
54013
54014                     for (; i < ln; ++i) {
54015                         node = nodes[i];
54016                         if (!node.isLeaf() && !node.isExpanded()) {
54017                             expanding++;
54018                             nodes[i].expand(recursive, function () {
54019                                 expanding--;
54020                                 if (callback && !expanding) {
54021                                     Ext.callback(callback, scope || me, [me.childNodes]);
54022                                 }
54023                             });
54024                         }
54025                     }
54026
54027                     if (!expanding && callback) {
54028                         Ext.callback(callback, scope || me, [me.childNodes]);                    }
54029                 },
54030
54031                 
54032                 collapse: function(recursive, callback, scope) {
54033                     var me = this;
54034
54035                     
54036                     if (!me.isLeaf()) {
54037                         
54038                         if (!me.collapsing && me.isExpanded()) {
54039                             me.fireEvent('beforecollapse', me, function() {
54040                                 me.set('expanded', false);
54041                                 me.fireEvent('collapse', me, me.childNodes, false);
54042
54043                                 
54044                                 if (recursive) {
54045                                     me.collapseChildren(true, callback, scope);
54046                                 }
54047                                 else {
54048                                     Ext.callback(callback, scope || me, [me.childNodes]);
54049                                 }
54050                             }, me);
54051                         }
54052                         
54053                         else if (recursive) {
54054                             me.collapseChildren(true, callback, scope);
54055                         }
54056                     }
54057                     
54058                     else {
54059                         Ext.callback(callback, scope || me, [me.childNodes]);
54060                     }
54061                 },
54062
54063                 
54064                 collapseChildren: function(recursive, callback, scope) {
54065                     var me = this,
54066                         i = 0,
54067                         nodes = me.childNodes,
54068                         ln = nodes.length,
54069                         node,
54070                         collapsing = 0;
54071
54072                     for (; i < ln; ++i) {
54073                         node = nodes[i];
54074                         if (!node.isLeaf() && node.isExpanded()) {
54075                             collapsing++;
54076                             nodes[i].collapse(recursive, function () {
54077                                 collapsing--;
54078                                 if (callback && !collapsing) {
54079                                     Ext.callback(callback, scope || me, [me.childNodes]);
54080                                 }
54081                             });
54082                         }
54083                     }
54084
54085                     if (!collapsing && callback) {
54086                         Ext.callback(callback, scope || me, [me.childNodes]);
54087                     }
54088                 }
54089             };
54090         }
54091     }
54092 });
54093
54094 Ext.define('Ext.data.NodeStore', {
54095     extend: 'Ext.data.Store',
54096     alias: 'store.node',
54097     requires: ['Ext.data.NodeInterface'],
54098     
54099     
54100     node: null,
54101     
54102     
54103     recursive: false,
54104     
54105         
54106     rootVisible: false,
54107     
54108     constructor: function(config) {
54109         var me = this,
54110             node;
54111             
54112         config = config || {};
54113         Ext.apply(me, config);
54114         
54115
54116         config.proxy = {type: 'proxy'};
54117         me.callParent([config]);
54118
54119         me.addEvents('expand', 'collapse', 'beforeexpand', 'beforecollapse');
54120         
54121         node = me.node;
54122         if (node) {
54123             me.node = null;
54124             me.setNode(node);
54125         }
54126     },
54127     
54128     setNode: function(node) {
54129         var me = this;
54130         
54131         if (me.node && me.node != node) {
54132             
54133             me.mun(me.node, {
54134                 expand: me.onNodeExpand,
54135                 collapse: me.onNodeCollapse,
54136                 append: me.onNodeAppend,
54137                 insert: me.onNodeInsert,
54138                 remove: me.onNodeRemove,
54139                 sort: me.onNodeSort,
54140                 scope: me
54141             });
54142             me.node = null;
54143         }
54144         
54145         if (node) {
54146             Ext.data.NodeInterface.decorate(node);
54147             me.removeAll();
54148             if (me.rootVisible) {
54149                 me.add(node);
54150             }
54151             me.mon(node, {
54152                 expand: me.onNodeExpand,
54153                 collapse: me.onNodeCollapse,
54154                 append: me.onNodeAppend,
54155                 insert: me.onNodeInsert,
54156                 remove: me.onNodeRemove,
54157                 sort: me.onNodeSort,
54158                 scope: me
54159             });
54160             me.node = node;
54161             if (node.isExpanded() && node.isLoaded()) {
54162                 me.onNodeExpand(node, node.childNodes, true);
54163             }
54164         }
54165     },
54166     
54167     onNodeSort: function(node, childNodes) {
54168         var me = this;
54169         
54170         if ((me.indexOf(node) !== -1 || (node === me.node && !me.rootVisible) && node.isExpanded())) {
54171             me.onNodeCollapse(node, childNodes, true);
54172             me.onNodeExpand(node, childNodes, true);
54173         }
54174     },
54175     
54176     onNodeExpand: function(parent, records, suppressEvent) {
54177         var me = this,
54178             insertIndex = me.indexOf(parent) + 1,
54179             ln = records ? records.length : 0,
54180             i, record;
54181             
54182         if (!me.recursive && parent !== me.node) {
54183             return;
54184         }
54185         
54186         if (!me.isVisible(parent)) {
54187             return;
54188         }
54189
54190         if (!suppressEvent && me.fireEvent('beforeexpand', parent, records, insertIndex) === false) {
54191             return;
54192         }
54193         
54194         if (ln) {
54195             me.insert(insertIndex, records);
54196             for (i = 0; i < ln; i++) {
54197                 record = records[i];
54198                 if (record.isExpanded()) {
54199                     if (record.isLoaded()) {
54200                         
54201                         me.onNodeExpand(record, record.childNodes, true);
54202                     }
54203                     else {
54204                         record.set('expanded', false);
54205                         record.expand();
54206                     }
54207                 }
54208             }
54209         }
54210
54211         if (!suppressEvent) {
54212             me.fireEvent('expand', parent, records);
54213         }
54214     },
54215
54216     onNodeCollapse: function(parent, records, suppressEvent) {
54217         var me = this,
54218             ln = records.length,
54219             collapseIndex = me.indexOf(parent) + 1,
54220             i, record;
54221             
54222         if (!me.recursive && parent !== me.node) {
54223             return;
54224         }
54225         
54226         if (!suppressEvent && me.fireEvent('beforecollapse', parent, records, collapseIndex) === false) {
54227             return;
54228         }
54229
54230         for (i = 0; i < ln; i++) {
54231             record = records[i];
54232             me.remove(record);
54233             if (record.isExpanded()) {
54234                 me.onNodeCollapse(record, record.childNodes, true);
54235             }
54236         }
54237         
54238         if (!suppressEvent) {
54239             me.fireEvent('collapse', parent, records, collapseIndex);
54240         }
54241     },
54242     
54243     onNodeAppend: function(parent, node, index) {
54244         var me = this,
54245             refNode, sibling;
54246
54247         if (me.isVisible(node)) {
54248             if (index === 0) {
54249                 refNode = parent;
54250             } else {
54251                 sibling = node.previousSibling;
54252                 while (sibling.isExpanded() && sibling.lastChild) {
54253                     sibling = sibling.lastChild;
54254                 }
54255                 refNode = sibling;
54256             }
54257             me.insert(me.indexOf(refNode) + 1, node);
54258             if (!node.isLeaf() && node.isExpanded()) {
54259                 if (node.isLoaded()) {
54260                     
54261                     me.onNodeExpand(node, node.childNodes, true);
54262                 }
54263                 else {
54264                     node.set('expanded', false);
54265                     node.expand();
54266                 }
54267             }
54268         } 
54269     },
54270     
54271     onNodeInsert: function(parent, node, refNode) {
54272         var me = this,
54273             index = this.indexOf(refNode);
54274             
54275         if (index != -1 && me.isVisible(node)) {
54276             me.insert(index, node);
54277             if (!node.isLeaf() && node.isExpanded()) {
54278                 if (node.isLoaded()) {
54279                     
54280                     me.onNodeExpand(node, node.childNodes, true);
54281                 }
54282                 else {
54283                     node.set('expanded', false);
54284                     node.expand();
54285                 }
54286             }
54287         }
54288     },
54289     
54290     onNodeRemove: function(parent, node, index) {
54291         var me = this;
54292         if (me.indexOf(node) != -1) {
54293             if (!node.isLeaf() && node.isExpanded()) {
54294                 me.onNodeCollapse(node, node.childNodes, true);
54295             }            
54296             me.remove(node);
54297         }
54298     },
54299     
54300     isVisible: function(node) {
54301         var parent = node.parentNode;
54302         while (parent) {
54303             if (parent === this.node && !this.rootVisible && parent.isExpanded()) {
54304                 return true;
54305             }
54306             
54307             if (this.indexOf(parent) === -1 || !parent.isExpanded()) {
54308                 return false;
54309             }
54310             
54311             parent = parent.parentNode;
54312         }
54313         return true;
54314     }
54315 });
54316
54317 Ext.define('Ext.data.Request', {
54318     
54319     action: undefined,
54320     
54321     
54322     params: undefined,
54323     
54324     
54325     method: 'GET',
54326     
54327     
54328     url: undefined,
54329
54330     
54331     constructor: function(config) {
54332         Ext.apply(this, config);
54333     }
54334 });
54335
54336 Ext.define('Ext.data.SequentialIdGenerator', {
54337     extend: 'Ext.data.IdGenerator',
54338     alias: 'idgen.sequential',
54339
54340     constructor: function() {
54341         var me = this;
54342
54343         me.callParent(arguments);
54344
54345         me.parts = [ me.prefix, ''];
54346     },
54347
54348     
54349     prefix: '',
54350
54351     
54352     seed: 1,
54353
54354     
54355     generate: function () {
54356         var me = this,
54357             parts = me.parts;
54358
54359         parts[1] = me.seed++;
54360         return parts.join('');
54361     }
54362 });
54363
54364
54365 Ext.define('Ext.data.Tree', {
54366     alias: 'data.tree',
54367
54368     mixins: {
54369         observable: "Ext.util.Observable"
54370     },
54371
54372     
54373     root: null,
54374
54375     
54376     constructor: function(root) {
54377         var me = this;
54378
54379         
54380
54381         me.mixins.observable.constructor.call(me);
54382
54383         if (root) {
54384             me.setRootNode(root);
54385         }
54386     },
54387
54388     
54389     getRootNode : function() {
54390         return this.root;
54391     },
54392
54393     
54394     setRootNode : function(node) {
54395         var me = this;
54396
54397         me.root = node;
54398         Ext.data.NodeInterface.decorate(node);
54399
54400         if (me.fireEvent('beforeappend', null, node) !== false) {
54401             node.set('root', true);
54402             node.updateInfo();
54403
54404             me.relayEvents(node, [
54405                 
54406                 "append",
54407
54408                 
54409                 "remove",
54410
54411                 
54412                 "move",
54413
54414                 
54415                 "insert",
54416
54417                 
54418                 "beforeappend",
54419
54420                 
54421                 "beforeremove",
54422
54423                 
54424                 "beforemove",
54425
54426                 
54427                 "beforeinsert",
54428
54429                  
54430                  "expand",
54431
54432                  
54433                  "collapse",
54434
54435                  
54436                  "beforeexpand",
54437
54438                  
54439                  "beforecollapse" ,
54440
54441                  
54442                  "rootchange"
54443             ]);
54444
54445             node.on({
54446                 scope: me,
54447                 insert: me.onNodeInsert,
54448                 append: me.onNodeAppend,
54449                 remove: me.onNodeRemove
54450             });
54451
54452             me.nodeHash = {};
54453             me.registerNode(node);
54454             me.fireEvent('append', null, node);
54455             me.fireEvent('rootchange', node);
54456         }
54457
54458         return node;
54459     },
54460
54461     
54462     flatten: function(){
54463         var nodes = [],
54464             hash = this.nodeHash,
54465             key;
54466
54467         for (key in hash) {
54468             if (hash.hasOwnProperty(key)) {
54469                 nodes.push(hash[key]);
54470             }
54471         }
54472         return nodes;
54473     },
54474
54475     
54476     onNodeInsert: function(parent, node) {
54477         this.registerNode(node, true);
54478     },
54479
54480     
54481     onNodeAppend: function(parent, node) {
54482         this.registerNode(node, true);
54483     },
54484
54485     
54486     onNodeRemove: function(parent, node) {
54487         this.unregisterNode(node, true);
54488     },
54489
54490     
54491     getNodeById : function(id) {
54492         return this.nodeHash[id];
54493     },
54494
54495     
54496     registerNode : function(node, includeChildren) {
54497         this.nodeHash[node.getId() || node.internalId] = node;
54498         if (includeChildren === true) {
54499             node.eachChild(function(child){
54500                 this.registerNode(child, true);
54501             }, this);
54502         }
54503     },
54504
54505     
54506     unregisterNode : function(node, includeChildren) {
54507         delete this.nodeHash[node.getId() || node.internalId];
54508         if (includeChildren === true) {
54509             node.eachChild(function(child){
54510                 this.unregisterNode(child, true);
54511             }, this);
54512         }
54513     },
54514
54515     
54516     sort: function(sorterFn, recursive) {
54517         this.getRootNode().sort(sorterFn, recursive);
54518     },
54519
54520      
54521     filter: function(filters, recursive) {
54522         this.getRootNode().filter(filters, recursive);
54523     }
54524 });
54525
54526 Ext.define('Ext.data.TreeStore', {
54527     extend: 'Ext.data.AbstractStore',
54528     alias: 'store.tree',
54529     requires: ['Ext.data.Tree', 'Ext.data.NodeInterface', 'Ext.data.NodeStore'],
54530
54531     
54532
54533     
54534     clearOnLoad : true,
54535
54536     
54537     nodeParam: 'node',
54538
54539     
54540     defaultRootId: 'root',
54541
54542     
54543     defaultRootProperty: 'children',
54544
54545     
54546     folderSort: false,
54547
54548     constructor: function(config) {
54549         var me = this,
54550             root,
54551             fields;
54552
54553         config = Ext.apply({}, config);
54554
54555         
54556         fields = config.fields || me.fields;
54557         if (!fields) {
54558             config.fields = [{name: 'text', type: 'string'}];
54559         }
54560
54561         me.callParent([config]);
54562
54563         
54564         me.tree = Ext.create('Ext.data.Tree');
54565
54566         me.relayEvents(me.tree, [
54567             
54568             "append",
54569
54570             
54571             "remove",
54572
54573             
54574             "move",
54575
54576             
54577             "insert",
54578
54579             
54580             "beforeappend",
54581
54582             
54583             "beforeremove",
54584
54585             
54586             "beforemove",
54587
54588             
54589             "beforeinsert",
54590
54591              
54592              "expand",
54593
54594              
54595              "collapse",
54596
54597              
54598              "beforeexpand",
54599
54600              
54601              "beforecollapse",
54602
54603              
54604              "rootchange"
54605         ]);
54606
54607         me.tree.on({
54608             scope: me,
54609             remove: me.onNodeRemove,
54610             
54611             
54612             beforeexpand: me.onBeforeNodeExpand,
54613             beforecollapse: me.onBeforeNodeCollapse,
54614             append: me.onNodeAdded,
54615             insert: me.onNodeAdded
54616         });
54617
54618         me.onBeforeSort();
54619
54620         root = me.root;
54621         if (root) {
54622             delete me.root;
54623             me.setRootNode(root);
54624         }
54625
54626         me.addEvents(
54627             
54628             'sort'
54629         );
54630
54631         if (Ext.isDefined(me.nodeParameter)) {
54632             if (Ext.isDefined(Ext.global.console)) {
54633                 Ext.global.console.warn('Ext.data.TreeStore: nodeParameter has been deprecated. Please use nodeParam instead.');
54634             }
54635             me.nodeParam = me.nodeParameter;
54636             delete me.nodeParameter;
54637         }
54638     },
54639
54640     
54641     setProxy: function(proxy) {
54642         var reader,
54643             needsRoot;
54644
54645         if (proxy instanceof Ext.data.proxy.Proxy) {
54646             
54647             needsRoot = Ext.isEmpty(proxy.getReader().root);
54648         } else if (Ext.isString(proxy)) {
54649             
54650             needsRoot = true;
54651         } else {
54652             
54653             reader = proxy.reader;
54654             needsRoot = !(reader && !Ext.isEmpty(reader.root));
54655         }
54656         proxy = this.callParent(arguments);
54657         if (needsRoot) {
54658             reader = proxy.getReader();
54659             reader.root = this.defaultRootProperty;
54660             
54661             reader.buildExtractors(true);
54662         }
54663     },
54664
54665     
54666     onBeforeSort: function() {
54667         if (this.folderSort) {
54668             this.sort({
54669                 property: 'leaf',
54670                 direction: 'ASC'
54671             }, 'prepend', false);
54672         }
54673     },
54674
54675     
54676     onBeforeNodeExpand: function(node, callback, scope) {
54677         if (node.isLoaded()) {
54678             Ext.callback(callback, scope || node, [node.childNodes]);
54679         }
54680         else if (node.isLoading()) {
54681             this.on('load', function() {
54682                 Ext.callback(callback, scope || node, [node.childNodes]);
54683             }, this, {single: true});
54684         }
54685         else {
54686             this.read({
54687                 node: node,
54688                 callback: function() {
54689                     Ext.callback(callback, scope || node, [node.childNodes]);
54690                 }
54691             });
54692         }
54693     },
54694
54695     
54696     getNewRecords: function() {
54697         return Ext.Array.filter(this.tree.flatten(), this.filterNew);
54698     },
54699
54700     
54701     getUpdatedRecords: function() {
54702         return Ext.Array.filter(this.tree.flatten(), this.filterUpdated);
54703     },
54704
54705     
54706     onBeforeNodeCollapse: function(node, callback, scope) {
54707         callback.call(scope || node, node.childNodes);
54708     },
54709
54710     onNodeRemove: function(parent, node) {
54711         var removed = this.removed;
54712
54713         if (!node.isReplace && Ext.Array.indexOf(removed, node) == -1) {
54714             removed.push(node);
54715         }
54716     },
54717
54718     onNodeAdded: function(parent, node) {
54719         var proxy = this.getProxy(),
54720             reader = proxy.getReader(),
54721             data = node.raw || node.data,
54722             dataRoot, children;
54723
54724         Ext.Array.remove(this.removed, node);
54725
54726         if (!node.isLeaf() && !node.isLoaded()) {
54727             dataRoot = reader.getRoot(data);
54728             if (dataRoot) {
54729                 this.fillNode(node, reader.extractData(dataRoot));
54730                 delete data[reader.root];
54731             }
54732         }
54733     },
54734
54735     
54736     setRootNode: function(root) {
54737         var me = this;
54738
54739         root = root || {};
54740         if (!root.isNode) {
54741             
54742             Ext.applyIf(root, {
54743                 id: me.defaultRootId,
54744                 text: 'Root',
54745                 allowDrag: false
54746             });
54747             root = Ext.ModelManager.create(root, me.model);
54748         }
54749         Ext.data.NodeInterface.decorate(root);
54750
54751         
54752         
54753         me.getProxy().getReader().buildExtractors(true);
54754
54755         
54756         me.tree.setRootNode(root);
54757
54758         
54759         if (!root.isLoaded() && (me.autoLoad === true || root.isExpanded())) {
54760             me.load({
54761                 node: root
54762             });
54763         }
54764
54765         return root;
54766     },
54767
54768     
54769     getRootNode: function() {
54770         return this.tree.getRootNode();
54771     },
54772
54773     
54774     getNodeById: function(id) {
54775         return this.tree.getNodeById(id);
54776     },
54777
54778     
54779     load: function(options) {
54780         options = options || {};
54781         options.params = options.params || {};
54782
54783         var me = this,
54784             node = options.node || me.tree.getRootNode(),
54785             root;
54786
54787         
54788         
54789         if (!node) {
54790             node = me.setRootNode({
54791                 expanded: true
54792             });
54793         }
54794
54795         if (me.clearOnLoad) {
54796             node.removeAll(true);
54797         }
54798
54799         Ext.applyIf(options, {
54800             node: node
54801         });
54802         options.params[me.nodeParam] = node ? node.getId() : 'root';
54803
54804         if (node) {
54805             node.set('loading', true);
54806         }
54807
54808         return me.callParent([options]);
54809     },
54810
54811
54812     
54813     fillNode: function(node, records) {
54814         var me = this,
54815             ln = records ? records.length : 0,
54816             i = 0, sortCollection;
54817
54818         if (ln && me.sortOnLoad && !me.remoteSort && me.sorters && me.sorters.items) {
54819             sortCollection = Ext.create('Ext.util.MixedCollection');
54820             sortCollection.addAll(records);
54821             sortCollection.sort(me.sorters.items);
54822             records = sortCollection.items;
54823         }
54824
54825         node.set('loaded', true);
54826         for (; i < ln; i++) {
54827             node.appendChild(records[i], undefined, true);
54828         }
54829
54830         return records;
54831     },
54832
54833     
54834     onProxyLoad: function(operation) {
54835         var me = this,
54836             successful = operation.wasSuccessful(),
54837             records = operation.getRecords(),
54838             node = operation.node;
54839
54840         me.loading = false;
54841         node.set('loading', false);
54842         if (successful) {
54843             records = me.fillNode(node, records);
54844         }
54845         
54846         
54847         
54848         
54849         me.fireEvent('read', me, operation.node, records, successful);
54850         me.fireEvent('load', me, operation.node, records, successful);
54851         
54852         Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]);
54853     },
54854
54855     
54856     onCreateRecords: function(records, operation, success) {
54857         if (success) {
54858             var i = 0,
54859                 length = records.length,
54860                 originalRecords = operation.records,
54861                 parentNode,
54862                 record,
54863                 original,
54864                 index;
54865
54866             
54867             for (; i < length; ++i) {
54868                 record = records[i];
54869                 original = originalRecords[i];
54870                 if (original) {
54871                     parentNode = original.parentNode;
54872                     if (parentNode) {
54873                         
54874                         original.isReplace = true;
54875                         parentNode.replaceChild(record, original);
54876                         delete original.isReplace;
54877                     }
54878                     record.phantom = false;
54879                 }
54880             }
54881         }
54882     },
54883
54884     
54885     onUpdateRecords: function(records, operation, success){
54886         if (success) {
54887             var me = this,
54888                 i = 0,
54889                 length = records.length,
54890                 data = me.data,
54891                 original,
54892                 parentNode,
54893                 record;
54894
54895             for (; i < length; ++i) {
54896                 record = records[i];
54897                 original = me.tree.getNodeById(record.getId());
54898                 parentNode = original.parentNode;
54899                 if (parentNode) {
54900                     
54901                     original.isReplace = true;
54902                     parentNode.replaceChild(record, original);
54903                     original.isReplace = false;
54904                 }
54905             }
54906         }
54907     },
54908
54909     
54910     onDestroyRecords: function(records, operation, success){
54911         if (success) {
54912             this.removed = [];
54913         }
54914     },
54915
54916     
54917     removeAll: function() {
54918         this.getRootNode().destroy(true);
54919         this.fireEvent('clear', this);
54920     },
54921
54922     
54923     doSort: function(sorterFn) {
54924         var me = this;
54925         if (me.remoteSort) {
54926             
54927             me.load();
54928         } else {
54929             me.tree.sort(sorterFn, true);
54930             me.fireEvent('datachanged', me);
54931         }
54932         me.fireEvent('sort', me);
54933     }
54934 });
54935
54936
54937 Ext.define('Ext.data.UuidGenerator', function () {
54938     var twoPow14 = Math.pow(2, 14),
54939         twoPow16 = Math.pow(2, 16),
54940         twoPow28 = Math.pow(2, 28),
54941         twoPow32 = Math.pow(2, 32);
54942
54943     function toHex (value, length) {
54944         var ret = value.toString(16);
54945         if (ret.length > length) {
54946             ret = ret.substring(ret.length - length); 
54947         } else if (ret.length < length) {
54948             ret = Ext.String.leftPad(ret, length, '0');
54949         }
54950         return ret;
54951     }
54952
54953     function rand (lo, hi) {
54954         var v = Math.random() * (hi - lo + 1);
54955         return Math.floor(v) + lo;
54956     }
54957
54958     function split (bignum) {
54959         if (typeof(bignum) == 'number') {
54960             var hi = Math.floor(bignum / twoPow32);
54961             return {
54962                 lo: Math.floor(bignum - hi * twoPow32),
54963                 hi: hi
54964             };
54965         }
54966         return bignum;
54967     }
54968
54969     return {
54970         extend: 'Ext.data.IdGenerator',
54971
54972         alias: 'idgen.uuid',
54973
54974         id: 'uuid', 
54975
54976         
54977
54978         
54979
54980         
54981         version: 4,
54982
54983         constructor: function() {
54984             var me = this;
54985
54986             me.callParent(arguments);
54987
54988             me.parts = [];
54989             me.init();
54990         },
54991
54992         generate: function () {
54993             var me = this,
54994                 parts = me.parts,
54995                 ts = me.timestamp;
54996
54997             
54998             parts[0] = toHex(ts.lo, 8);
54999             parts[1] = toHex(ts.hi & 0xFFFF, 4);
55000             parts[2] = toHex(((ts.hi >>> 16) & 0xFFF) | (me.version << 12), 4);
55001             parts[3] = toHex(0x80 | ((me.clockSeq >>> 8) & 0x3F), 2) +
55002                        toHex(me.clockSeq & 0xFF, 2);
55003             parts[4] = toHex(me.salt.hi, 4) + toHex(me.salt.lo, 8);
55004
55005             if (me.version == 4) {
55006                 me.init(); 
55007             } else {
55008                 
55009                 ++ts.lo;
55010                 if (ts.lo >= twoPow32) { 
55011                     ts.lo = 0;
55012                     ++ts.hi;
55013                 }
55014             }
55015
55016             return parts.join('-').toLowerCase();
55017         },
55018
55019         getRecId: function (rec) {
55020             return rec.getId();
55021         },
55022
55023         
55024         init: function () {
55025             var me = this,
55026                 salt, time;
55027
55028             if (me.version == 4) {
55029                 
55030                 
55031                 
55032                 
55033                 me.clockSeq = rand(0, twoPow14-1);
55034
55035                 
55036                 salt = me.salt || (me.salt = {});
55037                 time = me.timestamp || (me.timestamp = {});
55038
55039                 
55040                 salt.lo = rand(0, twoPow32-1);
55041                 salt.hi = rand(0, twoPow16-1);
55042                 time.lo = rand(0, twoPow32-1);
55043                 time.hi = rand(0, twoPow28-1);
55044             } else {
55045                 
55046                 me.salt = split(me.salt);
55047                 me.timestamp = split(me.timestamp);
55048
55049                 
55050                 
55051                 me.salt.hi |= 0x100;
55052             }
55053         },
55054
55055         
55056         reconfigure: function (config) {
55057             Ext.apply(this, config);
55058             this.init();
55059         }
55060     };
55061 }());
55062
55063
55064 Ext.define('Ext.data.XmlStore', {
55065     extend: 'Ext.data.Store',
55066     alternateClassName: 'Ext.data.XmlStore',
55067     alias: 'store.xml',
55068
55069     
55070     constructor: function(config){
55071         config = config || {};
55072         config = config || {};
55073
55074         Ext.applyIf(config, {
55075             proxy: {
55076                 type: 'ajax',
55077                 reader: 'xml',
55078                 writer: 'xml'
55079             }
55080         });
55081
55082         this.callParent([config]);
55083     }
55084 });
55085
55086
55087 Ext.define('Ext.data.proxy.Client', {
55088     extend: 'Ext.data.proxy.Proxy',
55089     alternateClassName: 'Ext.data.ClientProxy',
55090
55091     
55092     clear: function() {
55093     }
55094 });
55095
55096 Ext.define('Ext.data.proxy.JsonP', {
55097     extend: 'Ext.data.proxy.Server',
55098     alternateClassName: 'Ext.data.ScriptTagProxy',
55099     alias: ['proxy.jsonp', 'proxy.scripttag'],
55100     requires: ['Ext.data.JsonP'],
55101
55102     defaultWriterType: 'base',
55103
55104     
55105     callbackKey : 'callback',
55106
55107     
55108     recordParam: 'records',
55109
55110     
55111     autoAppendParams: true,
55112
55113     constructor: function(){
55114         this.addEvents(
55115             
55116             'exception'
55117         );
55118         this.callParent(arguments);
55119     },
55120
55121     
55122     doRequest: function(operation, callback, scope) {
55123         
55124         var me      = this,
55125             writer  = me.getWriter(),
55126             request = me.buildRequest(operation),
55127             params = request.params;
55128
55129         if (operation.allowWrite()) {
55130             request = writer.write(request);
55131         }
55132
55133         
55134         Ext.apply(request, {
55135             callbackKey: me.callbackKey,
55136             timeout: me.timeout,
55137             scope: me,
55138             disableCaching: false, 
55139             callback: me.createRequestCallback(request, operation, callback, scope)
55140         });
55141
55142         
55143         if (me.autoAppendParams) {
55144             request.params = {};
55145         }
55146
55147         request.jsonp = Ext.data.JsonP.request(request);
55148         
55149         request.params = params;
55150         operation.setStarted();
55151         me.lastRequest = request;
55152
55153         return request;
55154     },
55155
55156     
55157     createRequestCallback: function(request, operation, callback, scope) {
55158         var me = this;
55159
55160         return function(success, response, errorType) {
55161             delete me.lastRequest;
55162             me.processResponse(success, operation, request, response, callback, scope);
55163         };
55164     },
55165
55166     
55167     setException: function(operation, response) {
55168         operation.setException(operation.request.jsonp.errorType);
55169     },
55170
55171
55172     
55173     buildUrl: function(request) {
55174         var me      = this,
55175             url     = me.callParent(arguments),
55176             params  = Ext.apply({}, request.params),
55177             filters = params.filters,
55178             records,
55179             filter, i;
55180
55181         delete params.filters;
55182
55183         if (me.autoAppendParams) {
55184             url = Ext.urlAppend(url, Ext.Object.toQueryString(params));
55185         }
55186
55187         if (filters && filters.length) {
55188             for (i = 0; i < filters.length; i++) {
55189                 filter = filters[i];
55190
55191                 if (filter.value) {
55192                     url = Ext.urlAppend(url, filter.property + "=" + filter.value);
55193                 }
55194             }
55195         }
55196
55197         
55198         records = request.records;
55199
55200         if (Ext.isArray(records) && records.length > 0) {
55201             url = Ext.urlAppend(url, Ext.String.format("{0}={1}", me.recordParam, me.encodeRecords(records)));
55202         }
55203
55204         return url;
55205     },
55206
55207     
55208     destroy: function() {
55209         this.abort();
55210         this.callParent();
55211     },
55212
55213     
55214     abort: function() {
55215         var lastRequest = this.lastRequest;
55216         if (lastRequest) {
55217             Ext.data.JsonP.abort(lastRequest.jsonp);
55218         }
55219     },
55220
55221     
55222     encodeRecords: function(records) {
55223         var encoded = "",
55224             i = 0,
55225             len = records.length;
55226
55227         for (; i < len; i++) {
55228             encoded += Ext.Object.toQueryString(records[i].data);
55229         }
55230
55231         return encoded;
55232     }
55233 });
55234
55235
55236 Ext.define('Ext.data.proxy.WebStorage', {
55237     extend: 'Ext.data.proxy.Client',
55238     alternateClassName: 'Ext.data.WebStorageProxy',
55239
55240     
55241     id: undefined,
55242
55243     
55244     constructor: function(config) {
55245         this.callParent(arguments);
55246
55247         
55248         this.cache = {};
55249
55250
55251         
55252         this.id = this.id || (this.store ? this.store.storeId : undefined);
55253
55254
55255         this.initialize();
55256     },
55257
55258     
55259     create: function(operation, callback, scope) {
55260         var records = operation.records,
55261             length  = records.length,
55262             ids     = this.getIds(),
55263             id, record, i;
55264
55265         operation.setStarted();
55266
55267         for (i = 0; i < length; i++) {
55268             record = records[i];
55269
55270             if (record.phantom) {
55271                 record.phantom = false;
55272                 id = this.getNextId();
55273             } else {
55274                 id = record.getId();
55275             }
55276
55277             this.setRecord(record, id);
55278             ids.push(id);
55279         }
55280
55281         this.setIds(ids);
55282
55283         operation.setCompleted();
55284         operation.setSuccessful();
55285
55286         if (typeof callback == 'function') {
55287             callback.call(scope || this, operation);
55288         }
55289     },
55290
55291     
55292     read: function(operation, callback, scope) {
55293         
55294
55295         var records = [],
55296             ids     = this.getIds(),
55297             length  = ids.length,
55298             i, recordData, record;
55299
55300         
55301         if (operation.id) {
55302             record = this.getRecord(operation.id);
55303
55304             if (record) {
55305                 records.push(record);
55306                 operation.setSuccessful();
55307             }
55308         } else {
55309             for (i = 0; i < length; i++) {
55310                 records.push(this.getRecord(ids[i]));
55311             }
55312             operation.setSuccessful();
55313         }
55314
55315         operation.setCompleted();
55316
55317         operation.resultSet = Ext.create('Ext.data.ResultSet', {
55318             records: records,
55319             total  : records.length,
55320             loaded : true
55321         });
55322
55323         if (typeof callback == 'function') {
55324             callback.call(scope || this, operation);
55325         }
55326     },
55327
55328     
55329     update: function(operation, callback, scope) {
55330         var records = operation.records,
55331             length  = records.length,
55332             ids     = this.getIds(),
55333             record, id, i;
55334
55335         operation.setStarted();
55336
55337         for (i = 0; i < length; i++) {
55338             record = records[i];
55339             this.setRecord(record);
55340
55341             
55342             
55343             id = record.getId();
55344             if (id !== undefined && Ext.Array.indexOf(ids, id) == -1) {
55345                 ids.push(id);
55346             }
55347         }
55348         this.setIds(ids);
55349
55350         operation.setCompleted();
55351         operation.setSuccessful();
55352
55353         if (typeof callback == 'function') {
55354             callback.call(scope || this, operation);
55355         }
55356     },
55357
55358     
55359     destroy: function(operation, callback, scope) {
55360         var records = operation.records,
55361             length  = records.length,
55362             ids     = this.getIds(),
55363
55364             
55365             newIds  = [].concat(ids),
55366             i;
55367
55368         for (i = 0; i < length; i++) {
55369             Ext.Array.remove(newIds, records[i].getId());
55370             this.removeRecord(records[i], false);
55371         }
55372
55373         this.setIds(newIds);
55374
55375         operation.setCompleted();
55376         operation.setSuccessful();
55377
55378         if (typeof callback == 'function') {
55379             callback.call(scope || this, operation);
55380         }
55381     },
55382
55383     
55384     getRecord: function(id) {
55385         if (this.cache[id] === undefined) {
55386             var rawData = Ext.decode(this.getStorageObject().getItem(this.getRecordKey(id))),
55387                 data    = {},
55388                 Model   = this.model,
55389                 fields  = Model.prototype.fields.items,
55390                 length  = fields.length,
55391                 i, field, name, record;
55392
55393             for (i = 0; i < length; i++) {
55394                 field = fields[i];
55395                 name  = field.name;
55396
55397                 if (typeof field.decode == 'function') {
55398                     data[name] = field.decode(rawData[name]);
55399                 } else {
55400                     data[name] = rawData[name];
55401                 }
55402             }
55403
55404             record = new Model(data, id);
55405             record.phantom = false;
55406
55407             this.cache[id] = record;
55408         }
55409
55410         return this.cache[id];
55411     },
55412
55413     
55414     setRecord: function(record, id) {
55415         if (id) {
55416             record.setId(id);
55417         } else {
55418             id = record.getId();
55419         }
55420
55421         var me = this,
55422             rawData = record.data,
55423             data    = {},
55424             model   = me.model,
55425             fields  = model.prototype.fields.items,
55426             length  = fields.length,
55427             i = 0,
55428             field, name, obj, key;
55429
55430         for (; i < length; i++) {
55431             field = fields[i];
55432             name  = field.name;
55433
55434             if (typeof field.encode == 'function') {
55435                 data[name] = field.encode(rawData[name], record);
55436             } else {
55437                 data[name] = rawData[name];
55438             }
55439         }
55440
55441         obj = me.getStorageObject();
55442         key = me.getRecordKey(id);
55443
55444         
55445         me.cache[id] = record;
55446
55447         
55448         obj.removeItem(key);
55449         obj.setItem(key, Ext.encode(data));
55450     },
55451
55452     
55453     removeRecord: function(id, updateIds) {
55454         var me = this,
55455             ids;
55456
55457         if (id.isModel) {
55458             id = id.getId();
55459         }
55460
55461         if (updateIds !== false) {
55462             ids = me.getIds();
55463             Ext.Array.remove(ids, id);
55464             me.setIds(ids);
55465         }
55466
55467         me.getStorageObject().removeItem(me.getRecordKey(id));
55468     },
55469
55470     
55471     getRecordKey: function(id) {
55472         if (id.isModel) {
55473             id = id.getId();
55474         }
55475
55476         return Ext.String.format("{0}-{1}", this.id, id);
55477     },
55478
55479     
55480     getRecordCounterKey: function() {
55481         return Ext.String.format("{0}-counter", this.id);
55482     },
55483
55484     
55485     getIds: function() {
55486         var ids    = (this.getStorageObject().getItem(this.id) || "").split(","),
55487             length = ids.length,
55488             i;
55489
55490         if (length == 1 && ids[0] === "") {
55491             ids = [];
55492         } else {
55493             for (i = 0; i < length; i++) {
55494                 ids[i] = parseInt(ids[i], 10);
55495             }
55496         }
55497
55498         return ids;
55499     },
55500
55501     
55502     setIds: function(ids) {
55503         var obj = this.getStorageObject(),
55504             str = ids.join(",");
55505
55506         obj.removeItem(this.id);
55507
55508         if (!Ext.isEmpty(str)) {
55509             obj.setItem(this.id, str);
55510         }
55511     },
55512
55513     
55514     getNextId: function() {
55515         var obj  = this.getStorageObject(),
55516             key  = this.getRecordCounterKey(),
55517             last = obj.getItem(key),
55518             ids, id;
55519
55520         if (last === null) {
55521             ids = this.getIds();
55522             last = ids[ids.length - 1] || 0;
55523         }
55524
55525         id = parseInt(last, 10) + 1;
55526         obj.setItem(key, id);
55527
55528         return id;
55529     },
55530
55531     
55532     initialize: function() {
55533         var storageObject = this.getStorageObject();
55534         storageObject.setItem(this.id, storageObject.getItem(this.id) || "");
55535     },
55536
55537     
55538     clear: function() {
55539         var obj = this.getStorageObject(),
55540             ids = this.getIds(),
55541             len = ids.length,
55542             i;
55543
55544         
55545         for (i = 0; i < len; i++) {
55546             this.removeRecord(ids[i]);
55547         }
55548
55549         
55550         obj.removeItem(this.getRecordCounterKey());
55551         obj.removeItem(this.id);
55552     },
55553
55554     
55555     getStorageObject: function() {
55556     }
55557 });
55558
55559 Ext.define('Ext.data.proxy.LocalStorage', {
55560     extend: 'Ext.data.proxy.WebStorage',
55561     alias: 'proxy.localstorage',
55562     alternateClassName: 'Ext.data.LocalStorageProxy',
55563     
55564     
55565     getStorageObject: function() {
55566         return window.localStorage;
55567     }
55568 });
55569
55570 Ext.define('Ext.data.proxy.Memory', {
55571     extend: 'Ext.data.proxy.Client',
55572     alias: 'proxy.memory',
55573     alternateClassName: 'Ext.data.MemoryProxy',
55574
55575     
55576
55577     constructor: function(config) {
55578         this.callParent([config]);
55579
55580         
55581         this.setReader(this.reader);
55582     },
55583
55584     
55585     read: function(operation, callback, scope) {
55586         var me     = this,
55587             reader = me.getReader(),
55588             result = reader.read(me.data);
55589
55590         Ext.apply(operation, {
55591             resultSet: result
55592         });
55593
55594         operation.setCompleted();
55595         operation.setSuccessful();
55596         Ext.callback(callback, scope || me, [operation]);
55597     },
55598
55599     clear: Ext.emptyFn
55600 });
55601
55602
55603 Ext.define('Ext.data.proxy.Rest', {
55604     extend: 'Ext.data.proxy.Ajax',
55605     alternateClassName: 'Ext.data.RestProxy',
55606     alias : 'proxy.rest',
55607     
55608     
55609     appendId: true,
55610     
55611     
55612     
55613     
55614     batchActions: false,
55615     
55616     
55617     buildUrl: function(request) {
55618         var me        = this,
55619             operation = request.operation,
55620             records   = operation.records || [],
55621             record    = records[0],
55622             format    = me.format,
55623             url       = me.getUrl(request),
55624             id        = record ? record.getId() : operation.id;
55625         
55626         if (me.appendId && id) {
55627             if (!url.match(/\/$/)) {
55628                 url += '/';
55629             }
55630             
55631             url += id;
55632         }
55633         
55634         if (format) {
55635             if (!url.match(/\.$/)) {
55636                 url += '.';
55637             }
55638             
55639             url += format;
55640         }
55641         
55642         request.url = url;
55643         
55644         return me.callParent(arguments);
55645     }
55646 }, function() {
55647     Ext.apply(this.prototype, {
55648         
55649         actionMethods: {
55650             create : 'POST',
55651             read   : 'GET',
55652             update : 'PUT',
55653             destroy: 'DELETE'
55654         }
55655     });
55656 });
55657
55658
55659 Ext.define('Ext.data.proxy.SessionStorage', {
55660     extend: 'Ext.data.proxy.WebStorage',
55661     alias: 'proxy.sessionstorage',
55662     alternateClassName: 'Ext.data.SessionStorageProxy',
55663     
55664     
55665     getStorageObject: function() {
55666         return window.sessionStorage;
55667     }
55668 });
55669
55670
55671 Ext.define('Ext.data.reader.Array', {
55672     extend: 'Ext.data.reader.Json',
55673     alternateClassName: 'Ext.data.ArrayReader',
55674     alias : 'reader.array',
55675
55676     
55677     buildExtractors: function() {
55678         this.callParent(arguments);
55679         
55680         var fields = this.model.prototype.fields.items,
55681             i = 0,
55682             length = fields.length,
55683             extractorFunctions = [],
55684             map;
55685         
55686         for (; i < length; i++) {
55687             map = fields[i].mapping;
55688             extractorFunctions.push(function(index) {
55689                 return function(data) {
55690                     return data[index];
55691                 };
55692             }(map !== null ? map : i));
55693         }
55694         
55695         this.extractorFunctions = extractorFunctions;
55696     }
55697 });
55698
55699
55700 Ext.define('Ext.data.reader.Xml', {
55701     extend: 'Ext.data.reader.Reader',
55702     alternateClassName: 'Ext.data.XmlReader',
55703     alias : 'reader.xml',
55704
55705     
55706
55707     
55708     createAccessor: function(expr) {
55709         var me = this;
55710
55711         if (Ext.isEmpty(expr)) {
55712             return Ext.emptyFn;
55713         }
55714
55715         if (Ext.isFunction(expr)) {
55716             return expr;
55717         }
55718
55719         return function(root) {
55720             return me.getNodeValue(Ext.DomQuery.selectNode(expr, root));
55721         };
55722     },
55723
55724     getNodeValue: function(node) {
55725         if (node && node.firstChild) {
55726             return node.firstChild.nodeValue;
55727         }
55728         return undefined;
55729     },
55730
55731     
55732     getResponseData: function(response) {
55733         var xml = response.responseXML;
55734
55735
55736         return xml;
55737     },
55738
55739     
55740     getData: function(data) {
55741         return data.documentElement || data;
55742     },
55743
55744     
55745     getRoot: function(data) {
55746         var nodeName = data.nodeName,
55747             root     = this.root;
55748
55749         if (!root || (nodeName && nodeName == root)) {
55750             return data;
55751         } else if (Ext.DomQuery.isXml(data)) {
55752             
55753             
55754             
55755             return Ext.DomQuery.selectNode(root, data);
55756         }
55757     },
55758
55759     
55760     extractData: function(root) {
55761         var recordName = this.record;
55762
55763
55764         if (recordName != root.nodeName) {
55765             root = Ext.DomQuery.select(recordName, root);
55766         } else {
55767             root = [root];
55768         }
55769         return this.callParent([root]);
55770     },
55771
55772     
55773     getAssociatedDataRoot: function(data, associationName) {
55774         return Ext.DomQuery.select(associationName, data)[0];
55775     },
55776
55777     
55778     readRecords: function(doc) {
55779         
55780         if (Ext.isArray(doc)) {
55781             doc = doc[0];
55782         }
55783
55784         
55785         this.xmlData = doc;
55786         return this.callParent([doc]);
55787     }
55788 });
55789
55790 Ext.define('Ext.data.writer.Xml', {
55791     
55792     
55793     
55794     extend: 'Ext.data.writer.Writer',
55795     alternateClassName: 'Ext.data.XmlWriter',
55796     
55797     alias: 'writer.xml',
55798     
55799     
55800     
55801     
55802     documentRoot: 'xmlData',
55803     
55804     
55805     defaultDocumentRoot: 'xmlData',
55806
55807     
55808     header: '',
55809
55810     
55811     record: 'record',
55812
55813     
55814     writeRecords: function(request, data) {
55815         var me = this,
55816             xml = [],
55817             i = 0,
55818             len = data.length,
55819             root = me.documentRoot,
55820             record = me.record,
55821             needsRoot = data.length !== 1,
55822             item,
55823             key;
55824             
55825         
55826         xml.push(me.header || '');
55827         
55828         if (!root && needsRoot) {
55829             root = me.defaultDocumentRoot;
55830         }
55831         
55832         if (root) {
55833             xml.push('<', root, '>');
55834         }
55835             
55836         for (; i < len; ++i) {
55837             item = data[i];
55838             xml.push('<', record, '>');
55839             for (key in item) {
55840                 if (item.hasOwnProperty(key)) {
55841                     xml.push('<', key, '>', item[key], '</', key, '>');
55842                 }
55843             }
55844             xml.push('</', record, '>');
55845         }
55846         
55847         if (root) {
55848             xml.push('</', root, '>');
55849         }
55850             
55851         request.xmlData = xml.join('');
55852         return request;
55853     }
55854 });
55855
55856
55857 Ext.define('Ext.direct.Event', {
55858
55859     
55860
55861     alias: 'direct.event',
55862
55863     requires: ['Ext.direct.Manager'],
55864
55865     
55866
55867     status: true,
55868
55869     
55870     constructor: function(config) {
55871         Ext.apply(this, config);
55872     },
55873
55874     
55875     getData: function(){
55876         return this.data;
55877     }
55878 });
55879
55880
55881 Ext.define('Ext.direct.RemotingEvent', {
55882     
55883     
55884    
55885     extend: 'Ext.direct.Event',
55886     
55887     alias: 'direct.rpc',
55888     
55889     
55890     
55891     
55892     getTransaction: function(){
55893         return this.transaction || Ext.direct.Manager.getTransaction(this.tid);
55894     }
55895 });
55896
55897
55898 Ext.define('Ext.direct.ExceptionEvent', {
55899     
55900     
55901    
55902     extend: 'Ext.direct.RemotingEvent',
55903     
55904     alias: 'direct.exception',
55905     
55906     
55907    
55908    status: false
55909 });
55910
55911
55912 Ext.define('Ext.direct.Provider', {
55913
55914     
55915
55916    alias: 'direct.provider',
55917
55918     mixins: {
55919         observable: 'Ext.util.Observable'
55920     },
55921
55922     
55923
55924    
55925
55926     constructor : function(config){
55927         var me = this;
55928
55929         Ext.apply(me, config);
55930         me.addEvents(
55931             
55932             'connect',
55933             
55934             'disconnect',
55935             
55936             'data',
55937             
55938             'exception'
55939         );
55940         me.mixins.observable.constructor.call(me, config);
55941     },
55942
55943     
55944     isConnected: function(){
55945         return false;
55946     },
55947
55948     
55949     connect: Ext.emptyFn,
55950
55951     
55952     disconnect: Ext.emptyFn
55953 });
55954
55955
55956
55957 Ext.define('Ext.direct.JsonProvider', {
55958
55959     
55960
55961     extend: 'Ext.direct.Provider',
55962
55963     alias: 'direct.jsonprovider',
55964
55965     uses: ['Ext.direct.ExceptionEvent'],
55966
55967     
55968
55969    
55970    parseResponse: function(response){
55971         if (!Ext.isEmpty(response.responseText)) {
55972             if (Ext.isObject(response.responseText)) {
55973                 return response.responseText;
55974             }
55975             return Ext.decode(response.responseText);
55976         }
55977         return null;
55978     },
55979
55980     
55981     createEvents: function(response){
55982         var data = null,
55983             events = [],
55984             event,
55985             i = 0,
55986             len;
55987
55988         try{
55989             data = this.parseResponse(response);
55990         } catch(e) {
55991             event = Ext.create('Ext.direct.ExceptionEvent', {
55992                 data: e,
55993                 xhr: response,
55994                 code: Ext.direct.Manager.self.exceptions.PARSE,
55995                 message: 'Error parsing json response: \n\n ' + data
55996             });
55997             return [event];
55998         }
55999
56000         if (Ext.isArray(data)) {
56001             for (len = data.length; i < len; ++i) {
56002                 events.push(this.createEvent(data[i]));
56003             }
56004         } else {
56005             events.push(this.createEvent(data));
56006         }
56007         return events;
56008     },
56009
56010     
56011     createEvent: function(response){
56012         return Ext.create('direct.' + response.type, response);
56013     }
56014 });
56015
56016 Ext.define('Ext.direct.PollingProvider', {
56017     
56018     
56019     
56020     extend: 'Ext.direct.JsonProvider',
56021     
56022     alias: 'direct.pollingprovider',
56023     
56024     uses: ['Ext.direct.ExceptionEvent'],
56025     
56026     requires: ['Ext.Ajax', 'Ext.util.DelayedTask'],
56027     
56028     
56029     
56030     
56031     interval: 3000,
56032
56033     
56034     
56035     
56036
56037     
56038     constructor : function(config){
56039         this.callParent(arguments);
56040         this.addEvents(
56041             
56042             'beforepoll',            
56043             
56044             'poll'
56045         );
56046     },
56047
56048     
56049     isConnected: function(){
56050         return !!this.pollTask;
56051     },
56052
56053     
56054     connect: function(){
56055         var me = this, url = me.url;
56056         
56057         if (url && !me.pollTask) {
56058             me.pollTask = Ext.TaskManager.start({
56059                 run: function(){
56060                     if (me.fireEvent('beforepoll', me) !== false) {
56061                         if (Ext.isFunction(url)) {
56062                             url(me.baseParams);
56063                         } else {
56064                             Ext.Ajax.request({
56065                                 url: url,
56066                                 callback: me.onData,
56067                                 scope: me,
56068                                 params: me.baseParams
56069                             });
56070                         }
56071                     }
56072                 },
56073                 interval: me.interval,
56074                 scope: me
56075             });
56076             me.fireEvent('connect', me);
56077         } else if (!url) {
56078         }
56079     },
56080
56081     
56082     disconnect: function(){
56083         var me = this;
56084         
56085         if (me.pollTask) {
56086             Ext.TaskManager.stop(me.pollTask);
56087             delete me.pollTask;
56088             me.fireEvent('disconnect', me);
56089         }
56090     },
56091
56092     
56093     onData: function(opt, success, response){
56094         var me = this, 
56095             i = 0, 
56096             len,
56097             events;
56098         
56099         if (success) {
56100             events = me.createEvents(response);
56101             for (len = events.length; i < len; ++i) {
56102                 me.fireEvent('data', me, events[i]);
56103             }
56104         } else {
56105             me.fireEvent('data', me, Ext.create('Ext.direct.ExceptionEvent', {
56106                 data: null,
56107                 code: Ext.direct.Manager.self.exceptions.TRANSPORT,
56108                 message: 'Unable to connect to the server.',
56109                 xhr: response
56110             }));
56111         }
56112     }
56113 });
56114
56115 Ext.define('Ext.direct.RemotingMethod', {
56116
56117     constructor: function(config){
56118         var me = this,
56119             params = Ext.isDefined(config.params) ? config.params : config.len,
56120             name;
56121
56122         me.name = config.name;
56123         me.formHandler = config.formHandler;
56124         if (Ext.isNumber(params)) {
56125             
56126             me.len = params;
56127             me.ordered = true;
56128         } else {
56129             
56130             me.params = [];
56131             Ext.each(params, function(param){
56132                 name = Ext.isObject(param) ? param.name : param;
56133                 me.params.push(name);
56134             });
56135         }
56136     },
56137
56138     
56139     getCallData: function(args){
56140         var me = this,
56141             data = null,
56142             len  = me.len,
56143             params = me.params,
56144             callback,
56145             scope,
56146             name;
56147
56148         if (me.ordered) {
56149             callback = args[len];
56150             scope = args[len + 1];
56151             if (len !== 0) {
56152                 data = args.slice(0, len);
56153             }
56154         } else {
56155             data = Ext.apply({}, args[0]);
56156             callback = args[1];
56157             scope = args[2];
56158
56159             
56160             for (name in data) {
56161                 if (data.hasOwnProperty(name)) {
56162                     if (!Ext.Array.contains(params, name)) {
56163                         delete data[name];
56164                     }
56165                 }
56166             }
56167         }
56168
56169         return {
56170             data: data,
56171             callback: callback,
56172             scope: scope
56173         };
56174     }
56175 });
56176
56177
56178 Ext.define('Ext.direct.Transaction', {
56179     
56180     
56181    
56182     alias: 'direct.transaction',
56183     alternateClassName: 'Ext.Direct.Transaction',
56184    
56185     statics: {
56186         TRANSACTION_ID: 0
56187     },
56188    
56189     
56190
56191     
56192     constructor: function(config){
56193         var me = this;
56194         
56195         Ext.apply(me, config);
56196         me.id = ++me.self.TRANSACTION_ID;
56197         me.retryCount = 0;
56198     },
56199    
56200     send: function(){
56201          this.provider.queueTransaction(this);
56202     },
56203
56204     retry: function(){
56205         this.retryCount++;
56206         this.send();
56207     },
56208
56209     getProvider: function(){
56210         return this.provider;
56211     }
56212 });
56213
56214
56215 Ext.define('Ext.direct.RemotingProvider', {
56216     
56217     
56218    
56219     alias: 'direct.remotingprovider',
56220     
56221     extend: 'Ext.direct.JsonProvider', 
56222     
56223     requires: [
56224         'Ext.util.MixedCollection', 
56225         'Ext.util.DelayedTask', 
56226         'Ext.direct.Transaction',
56227         'Ext.direct.RemotingMethod'
56228     ],
56229    
56230     
56231    
56232    
56233     
56234     
56235     
56236     
56237     
56238     
56239     
56240     
56241     enableBuffer: 10,
56242     
56243     
56244     maxRetries: 1,
56245     
56246     
56247     timeout: undefined,
56248     
56249     constructor : function(config){
56250         var me = this;
56251         me.callParent(arguments);
56252         me.addEvents(
56253                         
56254             'beforecall',            
56255                         
56256             'call'
56257         );
56258         me.namespace = (Ext.isString(me.namespace)) ? Ext.ns(me.namespace) : me.namespace || window;
56259         me.transactions = Ext.create('Ext.util.MixedCollection');
56260         me.callBuffer = [];
56261     },
56262     
56263     
56264     initAPI : function(){
56265         var actions = this.actions,
56266             namespace = this.namespace,
56267             action,
56268             cls,
56269             methods,
56270             i,
56271             len,
56272             method;
56273             
56274         for (action in actions) {
56275             cls = namespace[action];
56276             if (!cls) {
56277                 cls = namespace[action] = {};
56278             }
56279             methods = actions[action];
56280             
56281             for (i = 0, len = methods.length; i < len; ++i) {
56282                 method = Ext.create('Ext.direct.RemotingMethod', methods[i]);
56283                 cls[method.name] = this.createHandler(action, method);
56284             }
56285         }
56286     },
56287     
56288     
56289     createHandler : function(action, method){
56290         var me = this,
56291             handler;
56292         
56293         if (!method.formHandler) {
56294             handler = function(){
56295                 me.configureRequest(action, method, Array.prototype.slice.call(arguments, 0));
56296             };
56297         } else {
56298             handler = function(form, callback, scope){
56299                 me.configureFormRequest(action, method, form, callback, scope);
56300             };
56301         }
56302         handler.directCfg = {
56303             action: action,
56304             method: method
56305         };
56306         return handler;
56307     },
56308     
56309     
56310     isConnected: function(){
56311         return !!this.connected;
56312     },
56313
56314     
56315     connect: function(){
56316         var me = this;
56317         
56318         if (me.url) {
56319             me.initAPI();
56320             me.connected = true;
56321             me.fireEvent('connect', me);
56322         } else if(!me.url) {
56323         }
56324     },
56325
56326     
56327     disconnect: function(){
56328         var me = this;
56329         
56330         if (me.connected) {
56331             me.connected = false;
56332             me.fireEvent('disconnect', me);
56333         }
56334     },
56335     
56336     
56337     runCallback: function(transaction, event){
56338         var funcName = event.status ? 'success' : 'failure',
56339             callback,
56340             result;
56341         
56342         if (transaction && transaction.callback) {
56343             callback = transaction.callback;
56344             result = Ext.isDefined(event.result) ? event.result : event.data;
56345         
56346             if (Ext.isFunction(callback)) {
56347                 callback(result, event);
56348             } else {
56349                 Ext.callback(callback[funcName], callback.scope, [result, event]);
56350                 Ext.callback(callback.callback, callback.scope, [result, event]);
56351             }
56352         }
56353     },
56354     
56355     
56356     onData: function(options, success, response){
56357         var me = this,
56358             i = 0,
56359             len,
56360             events,
56361             event,
56362             transaction,
56363             transactions;
56364             
56365         if (success) {
56366             events = me.createEvents(response);
56367             for (len = events.length; i < len; ++i) {
56368                 event = events[i];
56369                 transaction = me.getTransaction(event);
56370                 me.fireEvent('data', me, event);
56371                 if (transaction) {
56372                     me.runCallback(transaction, event, true);
56373                     Ext.direct.Manager.removeTransaction(transaction);
56374                 }
56375             }
56376         } else {
56377             transactions = [].concat(options.transaction);
56378             for (len = transactions.length; i < len; ++i) {
56379                 transaction = me.getTransaction(transactions[i]);
56380                 if (transaction && transaction.retryCount < me.maxRetries) {
56381                     transaction.retry();
56382                 } else {
56383                     event = Ext.create('Ext.direct.ExceptionEvent', {
56384                         data: null,
56385                         transaction: transaction,
56386                         code: Ext.direct.Manager.self.exceptions.TRANSPORT,
56387                         message: 'Unable to connect to the server.',
56388                         xhr: response
56389                     });
56390                     me.fireEvent('data', me, event);
56391                     if (transaction) {
56392                         me.runCallback(transaction, event, false);
56393                         Ext.direct.Manager.removeTransaction(transaction);
56394                     }
56395                 }
56396             }
56397         }
56398     },
56399     
56400     
56401     getTransaction: function(options){
56402         return options && options.tid ? Ext.direct.Manager.getTransaction(options.tid) : null;
56403     },
56404     
56405     
56406     configureRequest: function(action, method, args){
56407         var me = this,
56408             callData = method.getCallData(args),
56409             data = callData.data, 
56410             callback = callData.callback, 
56411             scope = callData.scope,
56412             transaction;
56413
56414         transaction = Ext.create('Ext.direct.Transaction', {
56415             provider: me,
56416             args: args,
56417             action: action,
56418             method: method.name,
56419             data: data,
56420             callback: scope && Ext.isFunction(callback) ? Ext.Function.bind(callback, scope) : callback
56421         });
56422
56423         if (me.fireEvent('beforecall', me, transaction, method) !== false) {
56424             Ext.direct.Manager.addTransaction(transaction);
56425             me.queueTransaction(transaction);
56426             me.fireEvent('call', me, transaction, method);
56427         }
56428     },
56429     
56430     
56431     getCallData: function(transaction){
56432         return {
56433             action: transaction.action,
56434             method: transaction.method,
56435             data: transaction.data,
56436             type: 'rpc',
56437             tid: transaction.id
56438         };
56439     },
56440     
56441     
56442     sendRequest : function(data){
56443         var me = this,
56444             request = {
56445                 url: me.url,
56446                 callback: me.onData,
56447                 scope: me,
56448                 transaction: data,
56449                 timeout: me.timeout
56450             }, callData,
56451             enableUrlEncode = me.enableUrlEncode,
56452             i = 0,
56453             len,
56454             params;
56455             
56456
56457         if (Ext.isArray(data)) {
56458             callData = [];
56459             for (len = data.length; i < len; ++i) {
56460                 callData.push(me.getCallData(data[i]));
56461             }
56462         } else {
56463             callData = me.getCallData(data);
56464         }
56465
56466         if (enableUrlEncode) {
56467             params = {};
56468             params[Ext.isString(enableUrlEncode) ? enableUrlEncode : 'data'] = Ext.encode(callData);
56469             request.params = params;
56470         } else {
56471             request.jsonData = callData;
56472         }
56473         Ext.Ajax.request(request);
56474     },
56475     
56476     
56477     queueTransaction: function(transaction){
56478         var me = this,
56479             enableBuffer = me.enableBuffer;
56480         
56481         if (transaction.form) {
56482             me.sendFormRequest(transaction);
56483             return;
56484         }
56485         
56486         me.callBuffer.push(transaction);
56487         if (enableBuffer) {
56488             if (!me.callTask) {
56489                 me.callTask = Ext.create('Ext.util.DelayedTask', me.combineAndSend, me);
56490             }
56491             me.callTask.delay(Ext.isNumber(enableBuffer) ? enableBuffer : 10);
56492         } else {
56493             me.combineAndSend();
56494         }
56495     },
56496     
56497     
56498     combineAndSend : function(){
56499         var buffer = this.callBuffer,
56500             len = buffer.length;
56501             
56502         if (len > 0) {
56503             this.sendRequest(len == 1 ? buffer[0] : buffer);
56504             this.callBuffer = [];
56505         }
56506     },
56507     
56508     
56509     configureFormRequest : function(action, method, form, callback, scope){
56510         var me = this,
56511             transaction = Ext.create('Ext.direct.Transaction', {
56512                 provider: me,
56513                 action: action,
56514                 method: method.name,
56515                 args: [form, callback, scope],
56516                 callback: scope && Ext.isFunction(callback) ? Ext.Function.bind(callback, scope) : callback,
56517                 isForm: true
56518             }),
56519             isUpload,
56520             params;
56521
56522         if (me.fireEvent('beforecall', me, transaction, method) !== false) {
56523             Ext.direct.Manager.addTransaction(transaction);
56524             isUpload = String(form.getAttribute("enctype")).toLowerCase() == 'multipart/form-data';
56525             
56526             params = {
56527                 extTID: transaction.id,
56528                 extAction: action,
56529                 extMethod: method.name,
56530                 extType: 'rpc',
56531                 extUpload: String(isUpload)
56532             };
56533             
56534             
56535             
56536             Ext.apply(transaction, {
56537                 form: Ext.getDom(form),
56538                 isUpload: isUpload,
56539                 params: callback && Ext.isObject(callback.params) ? Ext.apply(params, callback.params) : params
56540             });
56541             me.fireEvent('call', me, transaction, method);
56542             me.sendFormRequest(transaction);
56543         }
56544     },
56545     
56546     
56547     sendFormRequest: function(transaction){
56548         Ext.Ajax.request({
56549             url: this.url,
56550             params: transaction.params,
56551             callback: this.onData,
56552             scope: this,
56553             form: transaction.form,
56554             isUpload: transaction.isUpload,
56555             transaction: transaction
56556         });
56557     }
56558     
56559 });
56560
56561
56562 Ext.define('Ext.draw.Matrix', {
56563
56564     
56565
56566     requires: ['Ext.draw.Draw'],
56567
56568     
56569
56570     constructor: function(a, b, c, d, e, f) {
56571         if (a != null) {
56572             this.matrix = [[a, c, e], [b, d, f], [0, 0, 1]];
56573         }
56574         else {
56575             this.matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
56576         }
56577     },
56578
56579     add: function(a, b, c, d, e, f) {
56580         var me = this,
56581             out = [[], [], []],
56582             matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
56583             x,
56584             y,
56585             z,
56586             res;
56587
56588         for (x = 0; x < 3; x++) {
56589             for (y = 0; y < 3; y++) {
56590                 res = 0;
56591                 for (z = 0; z < 3; z++) {
56592                     res += me.matrix[x][z] * matrix[z][y];
56593                 }
56594                 out[x][y] = res;
56595             }
56596         }
56597         me.matrix = out;
56598     },
56599
56600     prepend: function(a, b, c, d, e, f) {
56601         var me = this,
56602             out = [[], [], []],
56603             matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
56604             x,
56605             y,
56606             z,
56607             res;
56608
56609         for (x = 0; x < 3; x++) {
56610             for (y = 0; y < 3; y++) {
56611                 res = 0;
56612                 for (z = 0; z < 3; z++) {
56613                     res += matrix[x][z] * me.matrix[z][y];
56614                 }
56615                 out[x][y] = res;
56616             }
56617         }
56618         me.matrix = out;
56619     },
56620
56621     invert: function() {
56622         var matrix = this.matrix,
56623             a = matrix[0][0],
56624             b = matrix[1][0],
56625             c = matrix[0][1],
56626             d = matrix[1][1],
56627             e = matrix[0][2],
56628             f = matrix[1][2],
56629             x = a * d - b * c;
56630         return new Ext.draw.Matrix(d / x, -b / x, -c / x, a / x, (c * f - d * e) / x, (b * e - a * f) / x);
56631     },
56632
56633     clone: function() {
56634         var matrix = this.matrix,
56635             a = matrix[0][0],
56636             b = matrix[1][0],
56637             c = matrix[0][1],
56638             d = matrix[1][1],
56639             e = matrix[0][2],
56640             f = matrix[1][2];
56641         return new Ext.draw.Matrix(a, b, c, d, e, f);
56642     },
56643
56644     translate: function(x, y) {
56645         this.prepend(1, 0, 0, 1, x, y);
56646     },
56647
56648     scale: function(x, y, cx, cy) {
56649         var me = this;
56650         if (y == null) {
56651             y = x;
56652         }
56653         me.add(1, 0, 0, 1, cx, cy);
56654         me.add(x, 0, 0, y, 0, 0);
56655         me.add(1, 0, 0, 1, -cx, -cy);
56656     },
56657
56658     rotate: function(a, x, y) {
56659         a = Ext.draw.Draw.rad(a);
56660         var me = this,
56661             cos = +Math.cos(a).toFixed(9),
56662             sin = +Math.sin(a).toFixed(9);
56663         me.add(cos, sin, -sin, cos, x, y);
56664         me.add(1, 0, 0, 1, -x, -y);
56665     },
56666
56667     x: function(x, y) {
56668         var matrix = this.matrix;
56669         return x * matrix[0][0] + y * matrix[0][1] + matrix[0][2];
56670     },
56671
56672     y: function(x, y) {
56673         var matrix = this.matrix;
56674         return x * matrix[1][0] + y * matrix[1][1] + matrix[1][2];
56675     },
56676
56677     get: function(i, j) {
56678         return + this.matrix[i][j].toFixed(4);
56679     },
56680
56681     toString: function() {
56682         var me = this;
56683         return [me.get(0, 0), me.get(0, 1), me.get(1, 0), me.get(1, 1), 0, 0].join();
56684     },
56685
56686     toSvg: function() {
56687         var me = this;
56688         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() + ")";
56689     },
56690
56691     toFilter: function() {
56692         var me = this;
56693         return "progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand',FilterType=bilinear,M11=" + me.get(0, 0) +
56694             ", M12=" + me.get(0, 1) + ", M21=" + me.get(1, 0) + ", M22=" + me.get(1, 1) +
56695             ", Dx=" + me.get(0, 2) + ", Dy=" + me.get(1, 2) + ")";
56696     },
56697
56698     offset: function() {
56699         var matrix = this.matrix;
56700         return [(matrix[0][2] || 0).toFixed(4), (matrix[1][2] || 0).toFixed(4)];
56701     },
56702
56703     
56704     split: function () {
56705         function norm(a) {
56706             return a[0] * a[0] + a[1] * a[1];
56707         }
56708         function normalize(a) {
56709             var mag = Math.sqrt(norm(a));
56710             a[0] /= mag;
56711             a[1] /= mag;
56712         }
56713         var matrix = this.matrix,
56714             out = {
56715                 translateX: matrix[0][2],
56716                 translateY: matrix[1][2]
56717             },
56718             row;
56719
56720         
56721         row = [[matrix[0][0], matrix[0][1]], [matrix[1][0], matrix[1][1]]];
56722         out.scaleX = Math.sqrt(norm(row[0]));
56723         normalize(row[0]);
56724
56725         out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1];
56726         row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear];
56727
56728         out.scaleY = Math.sqrt(norm(row[1]));
56729         normalize(row[1]);
56730         out.shear /= out.scaleY;
56731
56732         
56733         out.rotate = Math.asin(-row[0][1]);
56734
56735         out.isSimple = !+out.shear.toFixed(9) && (out.scaleX.toFixed(9) == out.scaleY.toFixed(9) || !out.rotate);
56736
56737         return out;
56738     }
56739 });
56740
56741
56742 Ext.define('Ext.draw.SpriteDD', {
56743     extend: 'Ext.dd.DragSource',
56744
56745     constructor : function(sprite, cfg){
56746         var me = this,
56747             el = sprite.el;
56748         me.sprite = sprite;
56749         me.el = el;
56750         me.dragData = {el: el, sprite: sprite};
56751         me.callParent([el, cfg]);
56752         me.sprite.setStyle('cursor', 'move');
56753     },
56754
56755     showFrame: Ext.emptyFn,
56756     createFrame : Ext.emptyFn,
56757
56758     getDragEl : function(e){
56759         return this.el;
56760     },
56761     
56762     getRegion: function() {
56763         var me = this,
56764             el = me.el,
56765             pos, x1, x2, y1, y2, t, r, b, l, bbox, sprite;
56766         
56767         sprite = me.sprite;
56768         bbox = sprite.getBBox();
56769         
56770         try {
56771             pos = Ext.Element.getXY(el);
56772         } catch (e) { }
56773
56774         if (!pos) {
56775             return null;
56776         }
56777
56778         x1 = pos[0];
56779         x2 = x1 + bbox.width;
56780         y1 = pos[1];
56781         y2 = y1 + bbox.height;
56782         
56783         return Ext.create('Ext.util.Region', y1, x2, y2, x1);
56784     },
56785
56786     
56787      
56788     startDrag: function(x, y) {
56789         var me = this,
56790             attr = me.sprite.attr;
56791         me.prev = me.sprite.surface.transformToViewBox(x, y);
56792     },
56793
56794     onDrag: function(e) {
56795         var xy = e.getXY(),
56796             me = this,
56797             sprite = me.sprite,
56798             attr = sprite.attr, dx, dy;
56799         xy = me.sprite.surface.transformToViewBox(xy[0], xy[1]);
56800         dx = xy[0] - me.prev[0];
56801         dy = xy[1] - me.prev[1];
56802         sprite.setAttributes({
56803             translate: {
56804                 x: attr.translation.x + dx,
56805                 y: attr.translation.y + dy
56806             }
56807         }, true);
56808         me.prev = xy;
56809     },
56810
56811     setDragElPos: function () {
56812         
56813         return false;
56814     }
56815 });
56816
56817 Ext.define('Ext.draw.Sprite', {
56818
56819     
56820
56821     mixins: {
56822         observable: 'Ext.util.Observable',
56823         animate: 'Ext.util.Animate'
56824     },
56825
56826     requires: ['Ext.draw.SpriteDD'],
56827
56828     
56829
56830     
56831
56832     
56833
56834     
56835
56836     
56837
56838     
56839
56840     
56841
56842     
56843
56844     
56845
56846     
56847
56848     
56849
56850     
56851
56852     
56853
56854     
56855
56856     
56857
56858     
56859
56860     
56861
56862     dirty: false,
56863     dirtyHidden: false,
56864     dirtyTransform: false,
56865     dirtyPath: true,
56866     dirtyFont: true,
56867     zIndexDirty: true,
56868     isSprite: true,
56869     zIndex: 0,
56870     fontProperties: [
56871         'font',
56872         'font-size',
56873         'font-weight',
56874         'font-style',
56875         'font-family',
56876         'text-anchor',
56877         'text'
56878     ],
56879     pathProperties: [
56880         'x',
56881         'y',
56882         'd',
56883         'path',
56884         'height',
56885         'width',
56886         'radius',
56887         'r',
56888         'rx',
56889         'ry',
56890         'cx',
56891         'cy'
56892     ],
56893     constructor: function(config) {
56894         var me = this;
56895         config = config || {};
56896         me.id = Ext.id(null, 'ext-sprite-');
56897         me.transformations = [];
56898         Ext.copyTo(this, config, 'surface,group,type,draggable');
56899         
56900         me.bbox = {};
56901         me.attr = {
56902             zIndex: 0,
56903             translation: {
56904                 x: null,
56905                 y: null
56906             },
56907             rotation: {
56908                 degrees: null,
56909                 x: null,
56910                 y: null
56911             },
56912             scaling: {
56913                 x: null,
56914                 y: null,
56915                 cx: null,
56916                 cy: null
56917             }
56918         };
56919         
56920         delete config.surface;
56921         delete config.group;
56922         delete config.type;
56923         delete config.draggable;
56924         me.setAttributes(config);
56925         me.addEvents(
56926             'beforedestroy',
56927             'destroy',
56928             'render',
56929             'mousedown',
56930             'mouseup',
56931             'mouseover',
56932             'mouseout',
56933             'mousemove',
56934             'click'
56935         );
56936         me.mixins.observable.constructor.apply(this, arguments);
56937     },
56938
56939     
56940
56941     initDraggable: function() {
56942         var me = this;
56943         me.draggable = true;
56944         
56945         if (!me.el) {
56946             me.surface.createSpriteElement(me);
56947         }
56948         me.dd = Ext.create('Ext.draw.SpriteDD', me, Ext.isBoolean(me.draggable) ? null : me.draggable);
56949         me.on('beforedestroy', me.dd.destroy, me.dd);
56950     },
56951
56952     
56953     setAttributes: function(attrs, redraw) {
56954         var me = this,
56955             fontProps = me.fontProperties,
56956             fontPropsLength = fontProps.length,
56957             pathProps = me.pathProperties,
56958             pathPropsLength = pathProps.length,
56959             hasSurface = !!me.surface,
56960             custom = hasSurface && me.surface.customAttributes || {},
56961             spriteAttrs = me.attr,
56962             attr, i, translate, translation, rotate, rotation, scale, scaling;
56963
56964         attrs = Ext.apply({}, attrs);
56965         for (attr in custom) {
56966             if (attrs.hasOwnProperty(attr) && typeof custom[attr] == "function") {
56967                 Ext.apply(attrs, custom[attr].apply(me, [].concat(attrs[attr])));
56968             }
56969         }
56970
56971         
56972         if (!!attrs.hidden !== !!spriteAttrs.hidden) {
56973             me.dirtyHidden = true;
56974         }
56975
56976         
56977         for (i = 0; i < pathPropsLength; i++) {
56978             attr = pathProps[i];
56979             if (attr in attrs && attrs[attr] !== spriteAttrs[attr]) {
56980                 me.dirtyPath = true;
56981                 break;
56982             }
56983         }
56984
56985         
56986         if ('zIndex' in attrs) {
56987             me.zIndexDirty = true;
56988         }
56989
56990         
56991         for (i = 0; i < fontPropsLength; i++) {
56992             attr = fontProps[i];
56993             if (attr in attrs && attrs[attr] !== spriteAttrs[attr]) {
56994                 me.dirtyFont = true;
56995                 break;
56996             }
56997         }
56998
56999         translate = attrs.translate;
57000         translation = spriteAttrs.translation;
57001         if (translate) {
57002             if ((translate.x && translate.x !== translation.x) ||
57003                 (translate.y && translate.y !== translation.y)) {
57004                 Ext.apply(translation, translate);
57005                 me.dirtyTransform = true;
57006             }
57007             delete attrs.translate;
57008         }
57009
57010         rotate = attrs.rotate;
57011         rotation = spriteAttrs.rotation;
57012         if (rotate) {
57013             if ((rotate.x && rotate.x !== rotation.x) ||
57014                 (rotate.y && rotate.y !== rotation.y) ||
57015                 (rotate.degrees && rotate.degrees !== rotation.degrees)) {
57016                 Ext.apply(rotation, rotate);
57017                 me.dirtyTransform = true;
57018             }
57019             delete attrs.rotate;
57020         }
57021
57022         scale = attrs.scale;
57023         scaling = spriteAttrs.scaling;
57024         if (scale) {
57025             if ((scale.x && scale.x !== scaling.x) ||
57026                 (scale.y && scale.y !== scaling.y) ||
57027                 (scale.cx && scale.cx !== scaling.cx) ||
57028                 (scale.cy && scale.cy !== scaling.cy)) {
57029                 Ext.apply(scaling, scale);
57030                 me.dirtyTransform = true;
57031             }
57032             delete attrs.scale;
57033         }
57034
57035         Ext.apply(spriteAttrs, attrs);
57036         me.dirty = true;
57037
57038         if (redraw === true && hasSurface) {
57039             me.redraw();
57040         }
57041         return this;
57042     },
57043
57044     
57045     getBBox: function() {
57046         return this.surface.getBBox(this);
57047     },
57048
57049     setText: function(text) {
57050         return this.surface.setText(this, text);
57051     },
57052
57053     
57054     hide: function(redraw) {
57055         this.setAttributes({
57056             hidden: true
57057         }, redraw);
57058         return this;
57059     },
57060
57061     
57062     show: function(redraw) {
57063         this.setAttributes({
57064             hidden: false
57065         }, redraw);
57066         return this;
57067     },
57068
57069     
57070     remove: function() {
57071         if (this.surface) {
57072             this.surface.remove(this);
57073             return true;
57074         }
57075         return false;
57076     },
57077
57078     onRemove: function() {
57079         this.surface.onRemove(this);
57080     },
57081
57082     
57083     destroy: function() {
57084         var me = this;
57085         if (me.fireEvent('beforedestroy', me) !== false) {
57086             me.remove();
57087             me.surface.onDestroy(me);
57088             me.clearListeners();
57089             me.fireEvent('destroy');
57090         }
57091     },
57092
57093     
57094     redraw: function() {
57095         this.surface.renderItem(this);
57096         return this;
57097     },
57098
57099     
57100     setStyle: function() {
57101         this.el.setStyle.apply(this.el, arguments);
57102         return this;
57103     },
57104
57105     
57106     addCls: function(obj) {
57107         this.surface.addCls(this, obj);
57108         return this;
57109     },
57110
57111     
57112     removeCls: function(obj) {
57113         this.surface.removeCls(this, obj);
57114         return this;
57115     }
57116 });
57117
57118
57119 Ext.define('Ext.draw.engine.Svg', {
57120
57121     
57122
57123     extend: 'Ext.draw.Surface',
57124
57125     requires: ['Ext.draw.Draw', 'Ext.draw.Sprite', 'Ext.draw.Matrix', 'Ext.Element'],
57126
57127     
57128
57129     engine: 'Svg',
57130
57131     trimRe: /^\s+|\s+$/g,
57132     spacesRe: /\s+/,
57133     xlink: "http:/" + "/www.w3.org/1999/xlink",
57134
57135     translateAttrs: {
57136         radius: "r",
57137         radiusX: "rx",
57138         radiusY: "ry",
57139         path: "d",
57140         lineWidth: "stroke-width",
57141         fillOpacity: "fill-opacity",
57142         strokeOpacity: "stroke-opacity",
57143         strokeLinejoin: "stroke-linejoin"
57144     },
57145     
57146     parsers: {},
57147
57148     minDefaults: {
57149         circle: {
57150             cx: 0,
57151             cy: 0,
57152             r: 0,
57153             fill: "none",
57154             stroke: null,
57155             "stroke-width": null,
57156             opacity: null,
57157             "fill-opacity": null,
57158             "stroke-opacity": null
57159         },
57160         ellipse: {
57161             cx: 0,
57162             cy: 0,
57163             rx: 0,
57164             ry: 0,
57165             fill: "none",
57166             stroke: null,
57167             "stroke-width": null,
57168             opacity: null,
57169             "fill-opacity": null,
57170             "stroke-opacity": null
57171         },
57172         rect: {
57173             x: 0,
57174             y: 0,
57175             width: 0,
57176             height: 0,
57177             rx: 0,
57178             ry: 0,
57179             fill: "none",
57180             stroke: null,
57181             "stroke-width": null,
57182             opacity: null,
57183             "fill-opacity": null,
57184             "stroke-opacity": null
57185         },
57186         text: {
57187             x: 0,
57188             y: 0,
57189             "text-anchor": "start",
57190             "font-family": null,
57191             "font-size": null,
57192             "font-weight": null,
57193             "font-style": null,
57194             fill: "#000",
57195             stroke: null,
57196             "stroke-width": null,
57197             opacity: null,
57198             "fill-opacity": null,
57199             "stroke-opacity": null
57200         },
57201         path: {
57202             d: "M0,0",
57203             fill: "none",
57204             stroke: null,
57205             "stroke-width": null,
57206             opacity: null,
57207             "fill-opacity": null,
57208             "stroke-opacity": null
57209         },
57210         image: {
57211             x: 0,
57212             y: 0,
57213             width: 0,
57214             height: 0,
57215             preserveAspectRatio: "none",
57216             opacity: null
57217         }
57218     },
57219
57220     createSvgElement: function(type, attrs) {
57221         var el = this.domRef.createElementNS("http:/" + "/www.w3.org/2000/svg", type),
57222             key;
57223         if (attrs) {
57224             for (key in attrs) {
57225                 el.setAttribute(key, String(attrs[key]));
57226             }
57227         }
57228         return el;
57229     },
57230
57231     createSpriteElement: function(sprite) {
57232         
57233         var el = this.createSvgElement(sprite.type);
57234         el.id = sprite.id;
57235         if (el.style) {
57236             el.style.webkitTapHighlightColor = "rgba(0,0,0,0)";
57237         }
57238         sprite.el = Ext.get(el);
57239         this.applyZIndex(sprite); 
57240         sprite.matrix = Ext.create('Ext.draw.Matrix');
57241         sprite.bbox = {
57242             plain: 0,
57243             transform: 0
57244         };
57245         sprite.fireEvent("render", sprite);
57246         return el;
57247     },
57248
57249     getBBox: function (sprite, isWithoutTransform) {
57250         var realPath = this["getPath" + sprite.type](sprite);
57251         if (isWithoutTransform) {
57252             sprite.bbox.plain = sprite.bbox.plain || Ext.draw.Draw.pathDimensions(realPath);
57253             return sprite.bbox.plain;
57254         }
57255         sprite.bbox.transform = sprite.bbox.transform || Ext.draw.Draw.pathDimensions(Ext.draw.Draw.mapPath(realPath, sprite.matrix));
57256         return sprite.bbox.transform;
57257     },
57258     
57259     getBBoxText: function (sprite) {
57260         var bbox = {},
57261             bb, height, width, i, ln, el;
57262
57263         if (sprite && sprite.el) {
57264             el = sprite.el.dom;
57265             try {
57266                 bbox = el.getBBox();
57267                 return bbox;
57268             } catch(e) {
57269                 
57270             }
57271             bbox = {x: bbox.x, y: Infinity, width: 0, height: 0};
57272             ln = el.getNumberOfChars();
57273             for (i = 0; i < ln; i++) {
57274                 bb = el.getExtentOfChar(i);
57275                 bbox.y = Math.min(bb.y, bbox.y);
57276                 height = bb.y + bb.height - bbox.y;
57277                 bbox.height = Math.max(bbox.height, height);
57278                 width = bb.x + bb.width - bbox.x;
57279                 bbox.width = Math.max(bbox.width, width);
57280             }
57281             return bbox;
57282         }
57283     },
57284
57285     hide: function() {
57286         Ext.get(this.el).hide();
57287     },
57288
57289     show: function() {
57290         Ext.get(this.el).show();
57291     },
57292
57293     hidePrim: function(sprite) {
57294         this.addCls(sprite, Ext.baseCSSPrefix + 'hide-visibility');
57295     },
57296
57297     showPrim: function(sprite) {
57298         this.removeCls(sprite, Ext.baseCSSPrefix + 'hide-visibility');
57299     },
57300
57301     getDefs: function() {
57302         return this._defs || (this._defs = this.createSvgElement("defs"));
57303     },
57304
57305     transform: function(sprite) {
57306         var me = this,
57307             matrix = Ext.create('Ext.draw.Matrix'),
57308             transforms = sprite.transformations,
57309             transformsLength = transforms.length,
57310             i = 0,
57311             transform, type;
57312             
57313         for (; i < transformsLength; i++) {
57314             transform = transforms[i];
57315             type = transform.type;
57316             if (type == "translate") {
57317                 matrix.translate(transform.x, transform.y);
57318             }
57319             else if (type == "rotate") {
57320                 matrix.rotate(transform.degrees, transform.x, transform.y);
57321             }
57322             else if (type == "scale") {
57323                 matrix.scale(transform.x, transform.y, transform.centerX, transform.centerY);
57324             }
57325         }
57326         sprite.matrix = matrix;
57327         sprite.el.set({transform: matrix.toSvg()});
57328     },
57329
57330     setSize: function(w, h) {
57331         var me = this,
57332             el = me.el;
57333         
57334         w = +w || me.width;
57335         h = +h || me.height;
57336         me.width = w;
57337         me.height = h;
57338
57339         el.setSize(w, h);
57340         el.set({
57341             width: w,
57342             height: h
57343         });
57344         me.callParent([w, h]);
57345     },
57346
57347     
57348     getRegion: function() {
57349         
57350         
57351         var svgXY = this.el.getXY(),
57352             rectXY = this.bgRect.getXY(),
57353             max = Math.max,
57354             x = max(svgXY[0], rectXY[0]),
57355             y = max(svgXY[1], rectXY[1]);
57356         return {
57357             left: x,
57358             top: y,
57359             right: x + this.width,
57360             bottom: y + this.height
57361         };
57362     },
57363
57364     onRemove: function(sprite) {
57365         if (sprite.el) {
57366             sprite.el.remove();
57367             delete sprite.el;
57368         }
57369         this.callParent(arguments);
57370     },
57371     
57372     setViewBox: function(x, y, width, height) {
57373         if (isFinite(x) && isFinite(y) && isFinite(width) && isFinite(height)) {
57374             this.callParent(arguments);
57375             this.el.dom.setAttribute("viewBox", [x, y, width, height].join(" "));
57376         }
57377     },
57378
57379     render: function (container) {
57380         var me = this;
57381         if (!me.el) {
57382             var width = me.width || 10,
57383                 height = me.height || 10,
57384                 el = me.createSvgElement('svg', {
57385                     xmlns: "http:/" + "/www.w3.org/2000/svg",
57386                     version: 1.1,
57387                     width: width,
57388                     height: height
57389                 }),
57390                 defs = me.getDefs(),
57391
57392                 
57393                 
57394                 
57395                 
57396                 bgRect = me.createSvgElement("rect", {
57397                     width: "100%",
57398                     height: "100%",
57399                     fill: "#000",
57400                     stroke: "none",
57401                     opacity: 0
57402                 }),
57403                 webkitRect;
57404             
57405                 if (Ext.isSafari3) {
57406                     
57407                     webkitRect = me.createSvgElement("rect", {
57408                         x: -10,
57409                         y: -10,
57410                         width: "110%",
57411                         height: "110%",
57412                         fill: "none",
57413                         stroke: "#000"
57414                     });
57415                 }
57416             el.appendChild(defs);
57417             if (Ext.isSafari3) {
57418                 el.appendChild(webkitRect);
57419             }
57420             el.appendChild(bgRect);
57421             container.appendChild(el);
57422             me.el = Ext.get(el);
57423             me.bgRect = Ext.get(bgRect);
57424             if (Ext.isSafari3) {
57425                 me.webkitRect = Ext.get(webkitRect);
57426                 me.webkitRect.hide();
57427             }
57428             me.el.on({
57429                 scope: me,
57430                 mouseup: me.onMouseUp,
57431                 mousedown: me.onMouseDown,
57432                 mouseover: me.onMouseOver,
57433                 mouseout: me.onMouseOut,
57434                 mousemove: me.onMouseMove,
57435                 mouseenter: me.onMouseEnter,
57436                 mouseleave: me.onMouseLeave,
57437                 click: me.onClick
57438             });
57439         }
57440         me.renderAll();
57441     },
57442
57443     
57444     onMouseEnter: function(e) {
57445         if (this.el.parent().getRegion().contains(e.getPoint())) {
57446             this.fireEvent('mouseenter', e);
57447         }
57448     },
57449
57450     
57451     onMouseLeave: function(e) {
57452         if (!this.el.parent().getRegion().contains(e.getPoint())) {
57453             this.fireEvent('mouseleave', e);
57454         }
57455     },
57456     
57457     processEvent: function(name, e) {
57458         var target = e.getTarget(),
57459             surface = this.surface,
57460             sprite;
57461
57462         this.fireEvent(name, e);
57463         
57464         if (target.nodeName == "tspan" && target.parentNode) {
57465             target = target.parentNode;
57466         }
57467         sprite = this.items.get(target.id);
57468         if (sprite) {
57469             sprite.fireEvent(name, sprite, e);
57470         }
57471     },
57472
57473     
57474     tuneText: function (sprite, attrs) {
57475         var el = sprite.el.dom,
57476             tspans = [],
57477             height, tspan, text, i, ln, texts, factor;
57478
57479         if (attrs.hasOwnProperty("text")) {
57480            tspans = this.setText(sprite, attrs.text);
57481         }
57482         
57483         if (tspans.length) {
57484             height = this.getBBoxText(sprite).height;
57485             for (i = 0, ln = tspans.length; i < ln; i++) {
57486                 
57487                 
57488                 factor = (Ext.isFF3_0 || Ext.isFF3_5) ? 2 : 4;
57489                 tspans[i].setAttribute("dy", i ? height * 1.2 : height / factor);
57490             }
57491             sprite.dirty = true;
57492         }
57493     },
57494
57495     setText: function(sprite, textString) {
57496          var me = this,
57497              el = sprite.el.dom,
57498              x = el.getAttribute("x"),
57499              tspans = [],
57500              height, tspan, text, i, ln, texts;
57501         
57502         while (el.firstChild) {
57503             el.removeChild(el.firstChild);
57504         }
57505         
57506         texts = String(textString).split("\n");
57507         for (i = 0, ln = texts.length; i < ln; i++) {
57508             text = texts[i];
57509             if (text) {
57510                 tspan = me.createSvgElement("tspan");
57511                 tspan.appendChild(document.createTextNode(Ext.htmlDecode(text)));
57512                 tspan.setAttribute("x", x);
57513                 el.appendChild(tspan);
57514                 tspans[i] = tspan;
57515             }
57516         }
57517         return tspans;
57518     },
57519
57520     renderAll: function() {
57521         this.items.each(this.renderItem, this);
57522     },
57523
57524     renderItem: function (sprite) {
57525         if (!this.el) {
57526             return;
57527         }
57528         if (!sprite.el) {
57529             this.createSpriteElement(sprite);
57530         }
57531         if (sprite.zIndexDirty) {
57532             this.applyZIndex(sprite);
57533         }
57534         if (sprite.dirty) {
57535             this.applyAttrs(sprite);
57536             this.applyTransformations(sprite);
57537         }
57538     },
57539
57540     redraw: function(sprite) {
57541         sprite.dirty = sprite.zIndexDirty = true;
57542         this.renderItem(sprite);
57543     },
57544
57545     applyAttrs: function (sprite) {
57546         var me = this,
57547             el = sprite.el,
57548             group = sprite.group,
57549             sattr = sprite.attr,
57550             parsers = me.parsers,
57551             
57552             
57553             
57554             gradientsMap = me.gradientsMap || {},
57555             safariFix = Ext.isSafari && !Ext.isStrict,
57556             groups, i, ln, attrs, font, key, style, name, rect;
57557
57558         if (group) {
57559             groups = [].concat(group);
57560             ln = groups.length;
57561             for (i = 0; i < ln; i++) {
57562                 group = groups[i];
57563                 me.getGroup(group).add(sprite);
57564             }
57565             delete sprite.group;
57566         }
57567         attrs = me.scrubAttrs(sprite) || {};
57568
57569         
57570             sprite.bbox.plain = 0;
57571             sprite.bbox.transform = 0;
57572             if (sprite.type == "circle" || sprite.type == "ellipse") {
57573                 attrs.cx = attrs.cx || attrs.x;
57574                 attrs.cy = attrs.cy || attrs.y;
57575             }
57576             else if (sprite.type == "rect") {
57577                 attrs.rx = attrs.ry = attrs.r;
57578             }
57579             else if (sprite.type == "path" && attrs.d) {
57580                 attrs.d = Ext.draw.Draw.pathToString(Ext.draw.Draw.pathToAbsolute(attrs.d));
57581             }
57582             sprite.dirtyPath = false;
57583         
57584         
57585         
57586         
57587
57588         if (attrs['clip-rect']) {
57589             me.setClip(sprite, attrs);
57590             delete attrs['clip-rect'];
57591         }
57592         if (sprite.type == 'text' && attrs.font && sprite.dirtyFont) {
57593             el.set({ style: "font: " + attrs.font});
57594             sprite.dirtyFont = false;
57595         }
57596         if (sprite.type == "image") {
57597             el.dom.setAttributeNS(me.xlink, "href", attrs.src);
57598         }
57599         Ext.applyIf(attrs, me.minDefaults[sprite.type]);
57600
57601         if (sprite.dirtyHidden) {
57602             (sattr.hidden) ? me.hidePrim(sprite) : me.showPrim(sprite);
57603             sprite.dirtyHidden = false;
57604         }
57605         for (key in attrs) {
57606             if (attrs.hasOwnProperty(key) && attrs[key] != null) {
57607                 
57608                 
57609                 
57610                 
57611                 
57612                 if (safariFix && ('color|stroke|fill'.indexOf(key) > -1) && (attrs[key] in gradientsMap)) {
57613                     attrs[key] = gradientsMap[attrs[key]];
57614                 }
57615                 if (key in parsers) {
57616                     el.dom.setAttribute(key, parsers[key](attrs[key], sprite, me));
57617                 } else {
57618                     el.dom.setAttribute(key, attrs[key]);
57619                 }
57620             }
57621         }
57622         
57623         if (sprite.type == 'text') {
57624             me.tuneText(sprite, attrs);
57625         }
57626
57627         
57628         style = sattr.style;
57629         if (style) {
57630             el.setStyle(style);
57631         }
57632
57633         sprite.dirty = false;
57634
57635         if (Ext.isSafari3) {
57636             
57637             me.webkitRect.show();
57638             setTimeout(function () {
57639                 me.webkitRect.hide();
57640             });
57641         }
57642     },
57643
57644     setClip: function(sprite, params) {
57645         var me = this,
57646             rect = params["clip-rect"],
57647             clipEl, clipPath;
57648         if (rect) {
57649             if (sprite.clip) {
57650                 sprite.clip.parentNode.parentNode.removeChild(sprite.clip.parentNode);
57651             }
57652             clipEl = me.createSvgElement('clipPath');
57653             clipPath = me.createSvgElement('rect');
57654             clipEl.id = Ext.id(null, 'ext-clip-');
57655             clipPath.setAttribute("x", rect.x);
57656             clipPath.setAttribute("y", rect.y);
57657             clipPath.setAttribute("width", rect.width);
57658             clipPath.setAttribute("height", rect.height);
57659             clipEl.appendChild(clipPath);
57660             me.getDefs().appendChild(clipEl);
57661             sprite.el.dom.setAttribute("clip-path", "url(#" + clipEl.id + ")");
57662             sprite.clip = clipPath;
57663         }
57664         
57665         
57666         
57667         
57668         
57669         
57670     },
57671
57672     
57673     applyZIndex: function(sprite) {
57674         var me = this,
57675             items = me.items,
57676             idx = items.indexOf(sprite),
57677             el = sprite.el,
57678             prevEl;
57679         if (me.el.dom.childNodes[idx + 2] !== el.dom) { 
57680             if (idx > 0) {
57681                 
57682                 do {
57683                     prevEl = items.getAt(--idx).el;
57684                 } while (!prevEl && idx > 0);
57685             }
57686             el.insertAfter(prevEl || me.bgRect);
57687         }
57688         sprite.zIndexDirty = false;
57689     },
57690
57691     createItem: function (config) {
57692         var sprite = Ext.create('Ext.draw.Sprite', config);
57693         sprite.surface = this;
57694         return sprite;
57695     },
57696
57697     addGradient: function(gradient) {
57698         gradient = Ext.draw.Draw.parseGradient(gradient);
57699         var me = this,
57700             ln = gradient.stops.length,
57701             vector = gradient.vector,
57702             
57703             
57704             
57705             usePlain = Ext.isSafari && !Ext.isStrict,
57706             gradientEl, stop, stopEl, i, gradientsMap;
57707             
57708         gradientsMap = me.gradientsMap || {};
57709         
57710         if (!usePlain) {
57711             if (gradient.type == "linear") {
57712                 gradientEl = me.createSvgElement("linearGradient");
57713                 gradientEl.setAttribute("x1", vector[0]);
57714                 gradientEl.setAttribute("y1", vector[1]);
57715                 gradientEl.setAttribute("x2", vector[2]);
57716                 gradientEl.setAttribute("y2", vector[3]);
57717             }
57718             else {
57719                 gradientEl = me.createSvgElement("radialGradient");
57720                 gradientEl.setAttribute("cx", gradient.centerX);
57721                 gradientEl.setAttribute("cy", gradient.centerY);
57722                 gradientEl.setAttribute("r", gradient.radius);
57723                 if (Ext.isNumber(gradient.focalX) && Ext.isNumber(gradient.focalY)) {
57724                     gradientEl.setAttribute("fx", gradient.focalX);
57725                     gradientEl.setAttribute("fy", gradient.focalY);
57726                 }
57727             }
57728             gradientEl.id = gradient.id;
57729             me.getDefs().appendChild(gradientEl);
57730             for (i = 0; i < ln; i++) {
57731                 stop = gradient.stops[i];
57732                 stopEl = me.createSvgElement("stop");
57733                 stopEl.setAttribute("offset", stop.offset + "%");
57734                 stopEl.setAttribute("stop-color", stop.color);
57735                 stopEl.setAttribute("stop-opacity",stop.opacity);
57736                 gradientEl.appendChild(stopEl);
57737             }
57738         } else {
57739             gradientsMap['url(#' + gradient.id + ')'] = gradient.stops[0].color;
57740         }
57741         me.gradientsMap = gradientsMap;
57742     },
57743
57744     
57745     hasCls: function(sprite, className) {
57746         return className && (' ' + (sprite.el.dom.getAttribute('class') || '') + ' ').indexOf(' ' + className + ' ') != -1;
57747     },
57748
57749     addCls: function(sprite, className) {
57750         var el = sprite.el,
57751             i,
57752             len,
57753             v,
57754             cls = [],
57755             curCls =  el.getAttribute('class') || '';
57756         
57757         if (!Ext.isArray(className)) {
57758             if (typeof className == 'string' && !this.hasCls(sprite, className)) {
57759                 el.set({ 'class': curCls + ' ' + className });
57760             }
57761         }
57762         else {
57763             for (i = 0, len = className.length; i < len; i++) {
57764                 v = className[i];
57765                 if (typeof v == 'string' && (' ' + curCls + ' ').indexOf(' ' + v + ' ') == -1) {
57766                     cls.push(v);
57767                 }
57768             }
57769             if (cls.length) {
57770                 el.set({ 'class': ' ' + cls.join(' ') });
57771             }
57772         }
57773     },
57774
57775     removeCls: function(sprite, className) {
57776         var me = this,
57777             el = sprite.el,
57778             curCls =  el.getAttribute('class') || '',
57779             i, idx, len, cls, elClasses;
57780         if (!Ext.isArray(className)){
57781             className = [className];
57782         }
57783         if (curCls) {
57784             elClasses = curCls.replace(me.trimRe, ' ').split(me.spacesRe);
57785             for (i = 0, len = className.length; i < len; i++) {
57786                 cls = className[i];
57787                 if (typeof cls == 'string') {
57788                     cls = cls.replace(me.trimRe, '');
57789                     idx = Ext.Array.indexOf(elClasses, cls);
57790                     if (idx != -1) {
57791                         Ext.Array.erase(elClasses, idx, 1);
57792                     }
57793                 }
57794             }
57795             el.set({ 'class': elClasses.join(' ') });
57796         }
57797     },
57798
57799     destroy: function() {
57800         var me = this;
57801         
57802         me.callParent();
57803         if (me.el) {
57804             me.el.remove();
57805         }
57806         delete me.el;
57807     }
57808 });
57809
57810
57811 Ext.define('Ext.draw.engine.Vml', {
57812
57813     
57814
57815     extend: 'Ext.draw.Surface',
57816
57817     requires: ['Ext.draw.Draw', 'Ext.draw.Color', 'Ext.draw.Sprite', 'Ext.draw.Matrix', 'Ext.Element'],
57818
57819     
57820
57821     engine: 'Vml',
57822
57823     map: {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"},
57824     bitesRe: /([clmz]),?([^clmz]*)/gi,
57825     valRe: /-?[^,\s-]+/g,
57826     fillUrlRe: /^url\(\s*['"]?([^\)]+?)['"]?\s*\)$/i,
57827     pathlike: /^(path|rect)$/,
57828     NonVmlPathRe: /[ahqstv]/ig, // Non-VML Pathing ops
57829     partialPathRe: /[clmz]/g,
57830     fontFamilyRe: /^['"]+|['"]+$/g,
57831     baseVmlCls: Ext.baseCSSPrefix + 'vml-base',
57832     vmlGroupCls: Ext.baseCSSPrefix + 'vml-group',
57833     spriteCls: Ext.baseCSSPrefix + 'vml-sprite',
57834     measureSpanCls: Ext.baseCSSPrefix + 'vml-measure-span',
57835     zoom: 21600,
57836     coordsize: 1000,
57837     coordorigin: '0 0',
57838
57839     // VML uses CSS z-index and therefore doesn't need sprites to be kept in zIndex order
57840     orderSpritesByZIndex: false,
57841
57842     
57843     
57844     path2vml: function (path) {
57845         var me = this,
57846             nonVML =  me.NonVmlPathRe,
57847             map = me.map,
57848             val = me.valRe,
57849             zoom = me.zoom,
57850             bites = me.bitesRe,
57851             command = Ext.Function.bind(Ext.draw.Draw.pathToAbsolute, Ext.draw.Draw),
57852             res, pa, p, r, i, ii, j, jj;
57853         if (String(path).match(nonVML)) {
57854             command = Ext.Function.bind(Ext.draw.Draw.path2curve, Ext.draw.Draw);
57855         } else if (!String(path).match(me.partialPathRe)) {
57856             res = String(path).replace(bites, function (all, command, args) {
57857                 var vals = [],
57858                     isMove = command.toLowerCase() == "m",
57859                     res = map[command];
57860                 args.replace(val, function (value) {
57861                     if (isMove && vals[length] == 2) {
57862                         res += vals + map[command == "m" ? "l" : "L"];
57863                         vals = [];
57864                     }
57865                     vals.push(Math.round(value * zoom));
57866                 });
57867                 return res + vals;
57868             });
57869             return res;
57870         }
57871         pa = command(path);
57872         res = [];
57873         for (i = 0, ii = pa.length; i < ii; i++) {
57874             p = pa[i];
57875             r = pa[i][0].toLowerCase();
57876             if (r == "z") {
57877                 r = "x";
57878             }
57879             for (j = 1, jj = p.length; j < jj; j++) {
57880                 r += Math.round(p[j] * me.zoom) + (j != jj - 1 ? "," : "");
57881             }
57882             res.push(r);
57883         }
57884         return res.join(" ");
57885     },
57886
57887     
57888     translateAttrs: {
57889         radius: "r",
57890         radiusX: "rx",
57891         radiusY: "ry",
57892         lineWidth: "stroke-width",
57893         fillOpacity: "fill-opacity",
57894         strokeOpacity: "stroke-opacity",
57895         strokeLinejoin: "stroke-linejoin"
57896     },
57897
57898     
57899     minDefaults: {
57900         circle: {
57901             fill: "none",
57902             stroke: null,
57903             "stroke-width": null,
57904             opacity: null,
57905             "fill-opacity": null,
57906             "stroke-opacity": null
57907         },
57908         ellipse: {
57909             cx: 0,
57910             cy: 0,
57911             rx: 0,
57912             ry: 0,
57913             fill: "none",
57914             stroke: null,
57915             "stroke-width": null,
57916             opacity: null,
57917             "fill-opacity": null,
57918             "stroke-opacity": null
57919         },
57920         rect: {
57921             x: 0,
57922             y: 0,
57923             width: 0,
57924             height: 0,
57925             rx: 0,
57926             ry: 0,
57927             fill: "none",
57928             stroke: null,
57929             "stroke-width": null,
57930             opacity: null,
57931             "fill-opacity": null,
57932             "stroke-opacity": null
57933         },
57934         text: {
57935             x: 0,
57936             y: 0,
57937             "text-anchor": "start",
57938             font: '10px "Arial"',
57939             fill: "#000",
57940             stroke: null,
57941             "stroke-width": null,
57942             opacity: null,
57943             "fill-opacity": null,
57944             "stroke-opacity": null
57945         },
57946         path: {
57947             d: "M0,0",
57948             fill: "none",
57949             stroke: null,
57950             "stroke-width": null,
57951             opacity: null,
57952             "fill-opacity": null,
57953             "stroke-opacity": null
57954         },
57955         image: {
57956             x: 0,
57957             y: 0,
57958             width: 0,
57959             height: 0,
57960             preserveAspectRatio: "none",
57961             opacity: null
57962         }
57963     },
57964
57965     
57966     onMouseEnter: function(e) {
57967         this.fireEvent("mouseenter", e);
57968     },
57969
57970     
57971     onMouseLeave: function(e) {
57972         this.fireEvent("mouseleave", e);
57973     },
57974
57975     
57976     processEvent: function(name, e) {
57977         var target = e.getTarget(),
57978             surface = this.surface,
57979             sprite;
57980         this.fireEvent(name, e);
57981         sprite = this.items.get(target.id);
57982         if (sprite) {
57983             sprite.fireEvent(name, sprite, e);
57984         }
57985     },
57986
57987     
57988     createSpriteElement: function(sprite) {
57989         var me = this,
57990             attr = sprite.attr,
57991             type = sprite.type,
57992             zoom = me.zoom,
57993             vml = sprite.vml || (sprite.vml = {}),
57994             round = Math.round,
57995             el = me.createNode('shape'),
57996             path, skew, textPath;
57997
57998         el.coordsize = zoom + ' ' + zoom;
57999         el.coordorigin = attr.coordorigin || "0 0";
58000         Ext.get(el).addCls(me.spriteCls);
58001         if (type == "text") {
58002             vml.path = path = me.createNode("path");
58003             path.textpathok = true;
58004             vml.textpath = textPath = me.createNode("textpath");
58005             textPath.on = true;
58006             el.appendChild(textPath);
58007             el.appendChild(path);
58008         }
58009         el.id = sprite.id;
58010         sprite.el = Ext.get(el);
58011         me.el.appendChild(el);
58012         if (type !== 'image') {
58013             skew = me.createNode("skew");
58014             skew.on = true;
58015             el.appendChild(skew);
58016             sprite.skew = skew;
58017         }
58018         sprite.matrix = Ext.create('Ext.draw.Matrix');
58019         sprite.bbox = {
58020             plain: null,
58021             transform: null
58022         };
58023         sprite.fireEvent("render", sprite);
58024         return sprite.el;
58025     },
58026
58027     
58028     getBBox: function (sprite, isWithoutTransform) {
58029         var realPath = this["getPath" + sprite.type](sprite);
58030         if (isWithoutTransform) {
58031             sprite.bbox.plain = sprite.bbox.plain || Ext.draw.Draw.pathDimensions(realPath);
58032             return sprite.bbox.plain;
58033         }
58034         sprite.bbox.transform = sprite.bbox.transform || Ext.draw.Draw.pathDimensions(Ext.draw.Draw.mapPath(realPath, sprite.matrix));
58035         return sprite.bbox.transform;
58036     },
58037
58038     getBBoxText: function (sprite) {
58039         var vml = sprite.vml;
58040         return {
58041             x: vml.X + (vml.bbx || 0) - vml.W / 2,
58042             y: vml.Y - vml.H / 2,
58043             width: vml.W,
58044             height: vml.H
58045         };
58046     },
58047
58048     applyAttrs: function (sprite) {
58049         var me = this,
58050             vml = sprite.vml,
58051             group = sprite.group,
58052             spriteAttr = sprite.attr,
58053             el = sprite.el,
58054             dom = el.dom,
58055             style, name, groups, i, ln, scrubbedAttrs, font, key, bbox;
58056
58057         if (group) {
58058             groups = [].concat(group);
58059             ln = groups.length;
58060             for (i = 0; i < ln; i++) {
58061                 group = groups[i];
58062                 me.getGroup(group).add(sprite);
58063             }
58064             delete sprite.group;
58065         }
58066         scrubbedAttrs = me.scrubAttrs(sprite) || {};
58067
58068         if (sprite.zIndexDirty) {
58069             me.setZIndex(sprite);
58070         }
58071
58072         
58073         Ext.applyIf(scrubbedAttrs, me.minDefaults[sprite.type]);
58074
58075         if (dom.href) {
58076             dom.href = scrubbedAttrs.href;
58077         }
58078         if (dom.title) {
58079             dom.title = scrubbedAttrs.title;
58080         }
58081         if (dom.target) {
58082             dom.target = scrubbedAttrs.target;
58083         }
58084         if (dom.cursor) {
58085             dom.cursor = scrubbedAttrs.cursor;
58086         }
58087
58088         
58089         if (sprite.dirtyHidden) {
58090             (scrubbedAttrs.hidden) ? me.hidePrim(sprite) : me.showPrim(sprite);
58091             sprite.dirtyHidden = false;
58092         }
58093
58094         
58095         if (sprite.dirtyPath) {
58096             if (sprite.type == "circle" || sprite.type == "ellipse") {
58097                 var cx = scrubbedAttrs.x,
58098                     cy = scrubbedAttrs.y,
58099                     rx = scrubbedAttrs.rx || scrubbedAttrs.r || 0,
58100                     ry = scrubbedAttrs.ry || scrubbedAttrs.r || 0;
58101                 dom.path = Ext.String.format("ar{0},{1},{2},{3},{4},{1},{4},{1}",
58102                             Math.round((cx - rx) * me.zoom),
58103                             Math.round((cy - ry) * me.zoom),
58104                             Math.round((cx + rx) * me.zoom),
58105                             Math.round((cy + ry) * me.zoom),
58106                             Math.round(cx * me.zoom));
58107                 sprite.dirtyPath = false;
58108             }
58109             else if (sprite.type !== "text") {
58110                 sprite.attr.path = scrubbedAttrs.path = me.setPaths(sprite, scrubbedAttrs) || scrubbedAttrs.path;
58111                 dom.path = me.path2vml(scrubbedAttrs.path);
58112                 sprite.dirtyPath = false;
58113             }
58114         }
58115
58116         
58117         if ("clip-rect" in scrubbedAttrs) {
58118             me.setClip(sprite, scrubbedAttrs);
58119         }
58120
58121         
58122         if (sprite.type == "text") {
58123             me.setTextAttributes(sprite, scrubbedAttrs);
58124         }
58125
58126         
58127         if (sprite.type == 'image' || scrubbedAttrs.opacity  || scrubbedAttrs['fill-opacity'] || scrubbedAttrs.fill) {
58128             me.setFill(sprite, scrubbedAttrs);
58129         }
58130
58131         
58132         if (scrubbedAttrs.stroke || scrubbedAttrs['stroke-opacity'] || scrubbedAttrs.fill) {
58133             me.setStroke(sprite, scrubbedAttrs);
58134         }
58135         
58136         
58137         style = spriteAttr.style;
58138         if (style) {
58139             el.setStyle(style);
58140         }
58141
58142         sprite.dirty = false;
58143     },
58144
58145     setZIndex: function(sprite) {
58146         if (sprite.el) {
58147             if (sprite.attr.zIndex != undefined) {
58148                 sprite.el.setStyle('zIndex', sprite.attr.zIndex);
58149             }
58150             sprite.zIndexDirty = false;
58151         }
58152     },
58153
58154     
58155     setPaths: function(sprite, params) {
58156         var spriteAttr = sprite.attr;
58157         
58158         sprite.bbox.plain = null;
58159         sprite.bbox.transform = null;
58160         if (sprite.type == 'circle') {
58161             spriteAttr.rx = spriteAttr.ry = params.r;
58162             return Ext.draw.Draw.ellipsePath(sprite);
58163         }
58164         else if (sprite.type == 'ellipse') {
58165             spriteAttr.rx = params.rx;
58166             spriteAttr.ry = params.ry;
58167             return Ext.draw.Draw.ellipsePath(sprite);
58168         }
58169         else if (sprite.type == 'rect' || sprite.type == 'image') {
58170             spriteAttr.rx = spriteAttr.ry = params.r;
58171             return Ext.draw.Draw.rectPath(sprite);
58172         }
58173         else if (sprite.type == 'path' && spriteAttr.path) {
58174             return Ext.draw.Draw.pathToAbsolute(spriteAttr.path);
58175         }
58176         return false;
58177     },
58178
58179     setFill: function(sprite, params) {
58180         var me = this,
58181             el = sprite.el,
58182             dom = el.dom,
58183             fillEl = dom.getElementsByTagName('fill')[0],
58184             opacity, gradient, fillUrl, rotation, angle;
58185
58186         if (fillEl) {
58187             dom.removeChild(fillEl);
58188         } else {
58189             fillEl = me.createNode('fill');
58190         }
58191         if (Ext.isArray(params.fill)) {
58192             params.fill = params.fill[0];
58193         }
58194         if (sprite.type == 'image') {
58195             fillEl.on = true;
58196             fillEl.src = params.src;
58197             fillEl.type = "tile";
58198             fillEl.rotate = true;
58199         } else if (params.fill == "none") {
58200             fillEl.on = false;
58201         } else {
58202             if (typeof params.opacity == "number") {
58203                 fillEl.opacity = params.opacity;
58204             }
58205             if (typeof params["fill-opacity"] == "number") {
58206                 fillEl.opacity = params["fill-opacity"];
58207             }
58208             fillEl.on = true;
58209             if (typeof params.fill == "string") {
58210                 fillUrl = params.fill.match(me.fillUrlRe);
58211                 if (fillUrl) {
58212                     fillUrl = fillUrl[1];
58213                     
58214                     if (fillUrl.charAt(0) == "#") {
58215                         gradient = me.gradientsColl.getByKey(fillUrl.substring(1));
58216                     }
58217                     if (gradient) {
58218                         
58219                         rotation = params.rotation;
58220                         angle = -(gradient.angle + 270 + (rotation ? rotation.degrees : 0)) % 360;
58221                         
58222                         if (angle === 0) {
58223                             angle = 180;
58224                         }
58225                         fillEl.angle = angle;
58226                         fillEl.type = "gradient";
58227                         fillEl.method = "sigma";
58228                         fillEl.colors = gradient.colors;
58229                     }
58230                     
58231                     else {
58232                         fillEl.src = fillUrl;
58233                         fillEl.type = "tile";
58234                         fillEl.rotate = true;
58235                     }
58236                 }
58237                 else {
58238                     fillEl.color = Ext.draw.Color.toHex(params.fill) || params.fill;
58239                     fillEl.src = "";
58240                     fillEl.type = "solid";
58241                 }
58242             }
58243         }
58244         dom.appendChild(fillEl);
58245     },
58246
58247     setStroke: function(sprite, params) {
58248         var me = this,
58249             el = sprite.el.dom,
58250             strokeEl = sprite.strokeEl,
58251             newStroke = false,
58252             width, opacity;
58253
58254         if (!strokeEl) {
58255             strokeEl = sprite.strokeEl = me.createNode("stroke");
58256             newStroke = true;
58257         }
58258         if (Ext.isArray(params.stroke)) {
58259             params.stroke = params.stroke[0];
58260         }
58261         if (!params.stroke || params.stroke == "none" || params.stroke == 0 || params["stroke-width"] == 0) {
58262             strokeEl.on = false;
58263         }
58264         else {
58265             strokeEl.on = true;
58266             if (params.stroke && !params.stroke.match(me.fillUrlRe)) {
58267                 
58268                 strokeEl.color = Ext.draw.Color.toHex(params.stroke);
58269             }
58270             strokeEl.joinstyle = params["stroke-linejoin"];
58271             strokeEl.endcap = params["stroke-linecap"] || "round";
58272             strokeEl.miterlimit = params["stroke-miterlimit"] || 8;
58273             width = parseFloat(params["stroke-width"] || 1) * 0.75;
58274             opacity = params["stroke-opacity"] || 1;
58275             
58276             if (Ext.isNumber(width) && width < 1) {
58277                 strokeEl.weight = 1;
58278                 strokeEl.opacity = opacity * width;
58279             }
58280             else {
58281                 strokeEl.weight = width;
58282                 strokeEl.opacity = opacity;
58283             }
58284         }
58285         if (newStroke) {
58286             el.appendChild(strokeEl);
58287         }
58288     },
58289
58290     setClip: function(sprite, params) {
58291         var me = this,
58292             el = sprite.el,
58293             clipEl = sprite.clipEl,
58294             rect = String(params["clip-rect"]).split(me.separatorRe);
58295         if (!clipEl) {
58296             clipEl = sprite.clipEl = me.el.insertFirst(Ext.getDoc().dom.createElement("div"));
58297             clipEl.addCls(Ext.baseCSSPrefix + 'vml-sprite');
58298         }
58299         if (rect.length == 4) {
58300             rect[2] = +rect[2] + (+rect[0]);
58301             rect[3] = +rect[3] + (+rect[1]);
58302             clipEl.setStyle("clip", Ext.String.format("rect({1}px {2}px {3}px {0}px)", rect[0], rect[1], rect[2], rect[3]));
58303             clipEl.setSize(me.el.width, me.el.height);
58304         }
58305         else {
58306             clipEl.setStyle("clip", "");
58307         }
58308     },
58309
58310     setTextAttributes: function(sprite, params) {
58311         var me = this,
58312             vml = sprite.vml,
58313             textStyle = vml.textpath.style,
58314             spanCacheStyle = me.span.style,
58315             zoom = me.zoom,
58316             round = Math.round,
58317             fontObj = {
58318                 fontSize: "font-size",
58319                 fontWeight: "font-weight",
58320                 fontStyle: "font-style"
58321             },
58322             fontProp,
58323             paramProp;
58324         if (sprite.dirtyFont) {
58325             if (params.font) {
58326                 textStyle.font = spanCacheStyle.font = params.font;
58327             }
58328             if (params["font-family"]) {
58329                 textStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(me.fontFamilyRe, "") + '"';
58330                 spanCacheStyle.fontFamily = params["font-family"];
58331             }
58332
58333             for (fontProp in fontObj) {
58334                 paramProp = params[fontObj[fontProp]];
58335                 if (paramProp) {
58336                     textStyle[fontProp] = spanCacheStyle[fontProp] = paramProp;
58337                 }
58338             }
58339
58340             me.setText(sprite, params.text);
58341             
58342             if (vml.textpath.string) {
58343                 me.span.innerHTML = String(vml.textpath.string).replace(/</g, "&#60;").replace(/&/g, "&#38;").replace(/\n/g, "<br>");
58344             }
58345             vml.W = me.span.offsetWidth;
58346             vml.H = me.span.offsetHeight + 2; 
58347
58348             
58349             if (params["text-anchor"] == "middle") {
58350                 textStyle["v-text-align"] = "center";
58351             }
58352             else if (params["text-anchor"] == "end") {
58353                 textStyle["v-text-align"] = "right";
58354                 vml.bbx = -Math.round(vml.W / 2);
58355             }
58356             else {
58357                 textStyle["v-text-align"] = "left";
58358                 vml.bbx = Math.round(vml.W / 2);
58359             }
58360         }
58361         vml.X = params.x;
58362         vml.Y = params.y;
58363         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);
58364         
58365         sprite.bbox.plain = null;
58366         sprite.bbox.transform = null;
58367         sprite.dirtyFont = false;
58368     },
58369     
58370     setText: function(sprite, text) {
58371         sprite.vml.textpath.string = Ext.htmlDecode(text);
58372     },
58373
58374     hide: function() {
58375         this.el.hide();
58376     },
58377
58378     show: function() {
58379         this.el.show();
58380     },
58381
58382     hidePrim: function(sprite) {
58383         sprite.el.addCls(Ext.baseCSSPrefix + 'hide-visibility');
58384     },
58385
58386     showPrim: function(sprite) {
58387         sprite.el.removeCls(Ext.baseCSSPrefix + 'hide-visibility');
58388     },
58389
58390     setSize: function(width, height) {
58391         var me = this;
58392         width = width || me.width;
58393         height = height || me.height;
58394         me.width = width;
58395         me.height = height;
58396
58397         if (me.el) {
58398             
58399             if (width != undefined) {
58400                 me.el.setWidth(width);
58401             }
58402             if (height != undefined) {
58403                 me.el.setHeight(height);
58404             }
58405
58406             
58407             me.applyViewBox();
58408
58409             me.callParent(arguments);
58410         }
58411     },
58412
58413     setViewBox: function(x, y, width, height) {
58414         this.callParent(arguments);
58415         this.viewBox = {
58416             x: x,
58417             y: y,
58418             width: width,
58419             height: height
58420         };
58421         this.applyViewBox();
58422     },
58423
58424     
58425     applyViewBox: function() {
58426         var me = this,
58427             viewBox = me.viewBox,
58428             width = me.width,
58429             height = me.height,
58430             viewBoxX, viewBoxY, viewBoxWidth, viewBoxHeight,
58431             relativeHeight, relativeWidth, size;
58432
58433         if (viewBox && (width || height)) {
58434             viewBoxX = viewBox.x;
58435             viewBoxY = viewBox.y;
58436             viewBoxWidth = viewBox.width;
58437             viewBoxHeight = viewBox.height;
58438             relativeHeight = height / viewBoxHeight;
58439             relativeWidth = width / viewBoxWidth;
58440
58441             if (viewBoxWidth * relativeHeight < width) {
58442                 viewBoxX -= (width - viewBoxWidth * relativeHeight) / 2 / relativeHeight;
58443             }
58444             if (viewBoxHeight * relativeWidth < height) {
58445                 viewBoxY -= (height - viewBoxHeight * relativeWidth) / 2 / relativeWidth;
58446             }
58447
58448             size = 1 / Math.max(viewBoxWidth / width, viewBoxHeight / height);
58449
58450             me.viewBoxShift = {
58451                 dx: -viewBoxX,
58452                 dy: -viewBoxY,
58453                 scale: size
58454             };
58455             me.items.each(function(item) {
58456                 me.transform(item);
58457             });
58458         }
58459     },
58460
58461     onAdd: function(item) {
58462         this.callParent(arguments);
58463         if (this.el) {
58464             this.renderItem(item);
58465         }
58466     },
58467
58468     onRemove: function(sprite) {
58469         if (sprite.el) {
58470             sprite.el.remove();
58471             delete sprite.el;
58472         }
58473         this.callParent(arguments);
58474     },
58475
58476     
58477     createNode : (function () {
58478         try {
58479             var doc = Ext.getDoc().dom;
58480             if (!doc.namespaces.rvml) {
58481                 doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
58482             }
58483             return function (tagName) {
58484                 return doc.createElement("<rvml:" + tagName + ' class="rvml">');
58485             };
58486         } catch (e) {
58487             return function (tagName) {
58488                 return doc.createElement("<" + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
58489             };
58490         }
58491     })(),
58492
58493     render: function (container) {
58494         var me = this,
58495             doc = Ext.getDoc().dom;
58496
58497         if (!me.el) {
58498             var el = doc.createElement("div");
58499             me.el = Ext.get(el);
58500             me.el.addCls(me.baseVmlCls);
58501
58502             
58503             me.span = doc.createElement("span");
58504             Ext.get(me.span).addCls(me.measureSpanCls);
58505             el.appendChild(me.span);
58506             me.el.setSize(me.width || 10, me.height || 10);
58507             container.appendChild(el);
58508             me.el.on({
58509                 scope: me,
58510                 mouseup: me.onMouseUp,
58511                 mousedown: me.onMouseDown,
58512                 mouseover: me.onMouseOver,
58513                 mouseout: me.onMouseOut,
58514                 mousemove: me.onMouseMove,
58515                 mouseenter: me.onMouseEnter,
58516                 mouseleave: me.onMouseLeave,
58517                 click: me.onClick
58518             });
58519         }
58520         me.renderAll();
58521     },
58522
58523     renderAll: function() {
58524         this.items.each(this.renderItem, this);
58525     },
58526
58527     redraw: function(sprite) {
58528         sprite.dirty = true;
58529         this.renderItem(sprite);
58530     },
58531
58532     renderItem: function (sprite) {
58533         
58534         if (!this.el) {
58535             return;
58536         }
58537
58538         
58539         if (!sprite.el) {
58540             this.createSpriteElement(sprite);
58541         }
58542
58543         if (sprite.dirty) {
58544             this.applyAttrs(sprite);
58545             if (sprite.dirtyTransform) {
58546                 this.applyTransformations(sprite);
58547             }
58548         }
58549     },
58550
58551     rotationCompensation: function (deg, dx, dy) {
58552         var matrix = Ext.create('Ext.draw.Matrix');
58553         matrix.rotate(-deg, 0.5, 0.5);
58554         return {
58555             x: matrix.x(dx, dy),
58556             y: matrix.y(dx, dy)
58557         };
58558     },
58559
58560     extractTransform: function (sprite) {
58561         var me = this,
58562             matrix = Ext.create('Ext.draw.Matrix'), scale,
58563             transformstions, tranformationsLength,
58564             transform, i = 0,
58565             shift = me.viewBoxShift;
58566
58567         for(transformstions = sprite.transformations, tranformationsLength = transformstions.length;
58568             i < tranformationsLength; i ++) {
58569             transform = transformstions[i];
58570             switch (transform.type) {
58571                 case 'translate' :
58572                     matrix.translate(transform.x, transform.y);
58573                     break;
58574                 case 'rotate':
58575                     matrix.rotate(transform.degrees, transform.x, transform.y);
58576                     break;
58577                 case 'scale':
58578                     matrix.scale(transform.x || transform.scale, transform.y || transform.scale, transform.centerX, transform.centerY);
58579                     break;
58580             }
58581         }
58582
58583         if (shift) {
58584             matrix.add(1, 0, 0, 1, shift.dx, shift.dy);
58585             matrix.prepend(shift.scale, 0, 0, shift.scale, 0, 0);
58586         }
58587         
58588         return sprite.matrix = matrix;
58589     },
58590
58591     setSimpleCoords: function(sprite, sx, sy, dx, dy, rotate) {
58592         var me = this,
58593             matrix = sprite.matrix,
58594             dom = sprite.el.dom,
58595             style = dom.style,
58596             yFlipper = 1,
58597             flip = "",
58598             fill = dom.getElementsByTagName('fill')[0],
58599             kx = me.zoom / sx,
58600             ky = me.zoom / sy,
58601             rotationCompensation;
58602         if (!sx || !sy) {
58603             return;
58604         }
58605         dom.coordsize = Math.abs(kx) + ' ' + Math.abs(ky);
58606         style.rotation = rotate * (sx * sy < 0 ? -1 : 1);
58607         if (rotate) {
58608             rotationCompensation = me.rotationCompensation(rotate, dx, dy);
58609             dx = rotationCompensation.x;
58610             dy = rotationCompensation.y;
58611         }
58612         if (sx < 0) {
58613             flip += "x"
58614         }
58615         if (sy < 0) {
58616             flip += " y";
58617             yFlipper = -1;
58618         }
58619         style.flip = flip;
58620         dom.coordorigin = (dx * -kx) + ' ' + (dy * -ky);
58621         if (fill) {
58622             dom.removeChild(fill);
58623             rotationCompensation = me.rotationCompensation(rotate, matrix.x(sprite.x, sprite.y), matrix.y(sprite.x, sprite.y));
58624             fill.position = rotationCompensation.x * yFlipper + ' ' + rotationCompensation.y * yFlipper;
58625             fill.size = sprite.width * Math.abs(sx) + ' ' + sprite.height * Math.abs(sy);
58626             dom.appendChild(fill);
58627         }
58628     },
58629
58630     transform : function (sprite) {
58631         var me = this,
58632             el = sprite.el,
58633             skew = sprite.skew,
58634             dom = el.dom,
58635             domStyle = dom.style,
58636             matrix = me.extractTransform(sprite).clone(),
58637             split, zoom = me.zoom,
58638             fill = dom.getElementsByTagName('fill')[0],
58639             isPatt = !String(sprite.fill).indexOf("url("),
58640             offset, c;
58641
58642
58643         
58644
58645         if (sprite.type != "image" && skew && !isPatt) {
58646             
58647             skew.matrix = matrix.toString();
58648             
58649             
58650             
58651             offset = matrix.offset();
58652             if (offset[0] > 32767) {
58653                 offset[0] = 32767;
58654             } else if (offset[0] < -32768) {
58655                 offset[0] = -32768
58656             }
58657             if (offset[1] > 32767) {
58658                 offset[1] = 32767;
58659             } else if (offset[1] < -32768) {
58660                 offset[1] = -32768
58661             }
58662             skew.offset = offset;
58663         } else {
58664             if (skew) {
58665                 skew.matrix = "1 0 0 1";
58666                 skew.offset = "0 0";
58667             }
58668             split = matrix.split();
58669             if (split.isSimple) {
58670                 domStyle.filter = '';
58671                 me.setSimpleCoords(sprite, split.scaleX, split.scaleY, split.translateX, split.translateY, split.rotate / Math.PI * 180);
58672             } else {
58673                 domStyle.filter = matrix.toFilter();
58674                 var bb = me.getBBox(sprite),
58675                     dx = bb.x - sprite.x,
58676                     dy = bb.y - sprite.y;
58677                 dom.coordorigin = (dx * -zoom) + ' ' + (dy * -zoom);
58678                 if (fill) {
58679                     dom.removeChild(fill);
58680                     fill.position = dx + ' ' + dy;
58681                     fill.size = sprite.width * sprite.scale.x + ' ' + sprite.height * 1.1;
58682                     dom.appendChild(fill);
58683                 }
58684             }
58685         }
58686     },
58687
58688     createItem: function (config) {
58689         return Ext.create('Ext.draw.Sprite', config);
58690     },
58691
58692     getRegion: function() {
58693         return this.el.getRegion();
58694     },
58695
58696     addCls: function(sprite, className) {
58697         if (sprite && sprite.el) {
58698             sprite.el.addCls(className);
58699         }
58700     },
58701
58702     removeCls: function(sprite, className) {
58703         if (sprite && sprite.el) {
58704             sprite.el.removeCls(className);
58705         }
58706     },
58707
58708     
58709     addGradient: function(gradient) {
58710         var gradients = this.gradientsColl || (this.gradientsColl = Ext.create('Ext.util.MixedCollection')),
58711             colors = [],
58712             stops = Ext.create('Ext.util.MixedCollection');
58713
58714         
58715         stops.addAll(gradient.stops);
58716         stops.sortByKey("ASC", function(a, b) {
58717             a = parseInt(a, 10);
58718             b = parseInt(b, 10);
58719             return a > b ? 1 : (a < b ? -1 : 0);
58720         });
58721         stops.eachKey(function(k, v) {
58722             colors.push(k + "% " + v.color);
58723         });
58724
58725         gradients.add(gradient.id, {
58726             colors: colors.join(","),
58727             angle: gradient.angle
58728         });
58729     },
58730
58731     destroy: function() {
58732         var me = this;
58733         
58734         me.callParent(arguments);
58735         if (me.el) {
58736             me.el.remove();
58737         }
58738         delete me.el;
58739     }
58740 });
58741
58742
58743 Ext.define('Ext.fx.target.ElementCSS', {
58744
58745     
58746
58747     extend: 'Ext.fx.target.Element',
58748
58749     
58750
58751     setAttr: function(targetData, isFirstFrame) {
58752         var cssArr = {
58753                 attrs: [],
58754                 duration: [],
58755                 easing: []
58756             },
58757             ln = targetData.length,
58758             attributes,
58759             attrs,
58760             attr,
58761             easing,
58762             duration,
58763             o,
58764             i,
58765             j,
58766             ln2;
58767         for (i = 0; i < ln; i++) {
58768             attrs = targetData[i];
58769             duration = attrs.duration;
58770             easing = attrs.easing;
58771             attrs = attrs.attrs;
58772             for (attr in attrs) {
58773                 if (Ext.Array.indexOf(cssArr.attrs, attr) == -1) {
58774                     cssArr.attrs.push(attr.replace(/[A-Z]/g, function(v) {
58775                         return '-' + v.toLowerCase();
58776                     }));
58777                     cssArr.duration.push(duration + 'ms');
58778                     cssArr.easing.push(easing);
58779                 }
58780             }
58781         }
58782         attributes = cssArr.attrs.join(',');
58783         duration = cssArr.duration.join(',');
58784         easing = cssArr.easing.join(', ');
58785         for (i = 0; i < ln; i++) {
58786             attrs = targetData[i].attrs;
58787             for (attr in attrs) {
58788                 ln2 = attrs[attr].length;
58789                 for (j = 0; j < ln2; j++) {
58790                     o = attrs[attr][j];
58791                     o[0].setStyle(Ext.supports.CSS3Prefix + 'TransitionProperty', isFirstFrame ? '' : attributes);
58792                     o[0].setStyle(Ext.supports.CSS3Prefix + 'TransitionDuration', isFirstFrame ? '' : duration);
58793                     o[0].setStyle(Ext.supports.CSS3Prefix + 'TransitionTimingFunction', isFirstFrame ? '' : easing);
58794                     o[0].setStyle(attr, o[1]);
58795
58796                     
58797                     if (isFirstFrame) {
58798                         o = o[0].dom.offsetWidth;
58799                     }
58800                     else {
58801                         
58802                         o[0].on(Ext.supports.CSS3TransitionEnd, function() {
58803                             this.setStyle(Ext.supports.CSS3Prefix + 'TransitionProperty', null);
58804                             this.setStyle(Ext.supports.CSS3Prefix + 'TransitionDuration', null);
58805                             this.setStyle(Ext.supports.CSS3Prefix + 'TransitionTimingFunction', null);
58806                         }, o[0], { single: true });
58807                     }
58808                 }
58809             }
58810         }
58811     }
58812 });
58813
58814 Ext.define('Ext.fx.target.CompositeElementCSS', {
58815
58816     
58817
58818     extend: 'Ext.fx.target.CompositeElement',
58819
58820     requires: ['Ext.fx.target.ElementCSS'],
58821
58822     
58823     setAttr: function() {
58824         return Ext.fx.target.ElementCSS.prototype.setAttr.apply(this, arguments);
58825     }
58826 });
58827
58828 Ext.define('Ext.layout.container.AbstractFit', {
58829
58830     
58831
58832     extend: 'Ext.layout.container.Container',
58833
58834     
58835
58836     itemCls: Ext.baseCSSPrefix + 'fit-item',
58837     targetCls: Ext.baseCSSPrefix + 'layout-fit',
58838     type: 'fit'
58839 });
58840
58841 Ext.define('Ext.layout.container.Fit', {
58842
58843     
58844
58845     extend: 'Ext.layout.container.AbstractFit',
58846     alias: 'layout.fit',
58847     alternateClassName: 'Ext.layout.FitLayout',
58848     requires: ['Ext.layout.container.Box'],
58849
58850     
58851
58852     
58853     defaultMargins: {
58854         top: 0,
58855         right: 0,
58856         bottom: 0,
58857         left: 0
58858     },
58859
58860     
58861     onLayout : function() {
58862         var me = this,
58863             size,
58864             item,
58865             margins;
58866         me.callParent();
58867
58868         if (me.owner.items.length) {
58869             item = me.owner.items.get(0);
58870             margins = item.margins || me.defaultMargins;
58871             size = me.getLayoutTargetSize();
58872             size.width  -= margins.width;
58873             size.height -= margins.height;
58874             me.setItemBox(item, size);
58875
58876             
58877             
58878             if (margins.left || margins.top) {
58879                 item.setPosition(margins.left, margins.top);
58880             }
58881         }
58882     },
58883
58884     getTargetBox : function() {
58885         return this.getLayoutTargetSize();
58886     },
58887
58888     setItemBox : function(item, box) {
58889         var me = this;
58890         if (item && box.height > 0) {
58891             if (!me.owner.isFixedWidth()) {
58892                box.width = undefined;
58893             }
58894             if (!me.owner.isFixedHeight()) {
58895                box.height = undefined;
58896             }
58897             me.setItemSize(item, box.width, box.height);
58898         }
58899     },
58900
58901     configureItem: function(item) {
58902
58903         
58904         
58905         item.layoutManagedHeight = 0;
58906         item.layoutManagedWidth = 0;
58907
58908         this.callParent(arguments);
58909     }
58910 }, function() {
58911     
58912     
58913     this.prototype.renderItem = Ext.layout.container.Box.prototype.renderItem;
58914 });
58915
58916 Ext.define('Ext.layout.container.AbstractCard', {
58917
58918     
58919
58920     extend: 'Ext.layout.container.Fit',
58921
58922     
58923
58924     type: 'card',
58925
58926     sizeAllCards: false,
58927
58928     hideInactive: true,
58929
58930     
58931     deferredRender : false,
58932
58933     beforeLayout: function() {
58934         var me = this;
58935         me.getActiveItem();
58936         if (me.activeItem && me.deferredRender) {
58937             me.renderItems([me.activeItem], me.getRenderTarget());
58938             return true;
58939         }
58940         else {
58941             return this.callParent(arguments);
58942         }
58943     },
58944
58945     renderChildren: function () {
58946         if (!this.deferredRender) {
58947             this.getActiveItem();
58948             this.callParent();
58949         }
58950     },
58951
58952     onLayout: function() {
58953         var me = this,
58954             activeItem = me.activeItem,
58955             items = me.getVisibleItems(),
58956             ln = items.length,
58957             targetBox = me.getTargetBox(),
58958             i, item;
58959
58960         for (i = 0; i < ln; i++) {
58961             item = items[i];
58962             me.setItemBox(item, targetBox);
58963         }
58964
58965         if (!me.firstActivated && activeItem) {
58966             if (activeItem.fireEvent('beforeactivate', activeItem) !== false) {
58967                 activeItem.fireEvent('activate', activeItem);
58968             }
58969             me.firstActivated = true;
58970         }
58971     },
58972
58973     isValidParent : function(item, target, position) {
58974         
58975         
58976         var itemEl = item.el ? item.el.dom : Ext.getDom(item);
58977         return (itemEl && itemEl.parentNode === (target.dom || target)) || false;
58978     },
58979
58980     
58981     getActiveItem: function() {
58982         var me = this;
58983         if (!me.activeItem && me.owner) {
58984             me.activeItem = me.parseActiveItem(me.owner.activeItem);
58985         }
58986
58987         if (me.activeItem && me.owner.items.indexOf(me.activeItem) != -1) {
58988             return me.activeItem;
58989         }
58990
58991         return null;
58992     },
58993
58994     
58995     parseActiveItem: function(item) {
58996         if (item && item.isComponent) {
58997             return item;
58998         }
58999         else if (typeof item == 'number' || item === undefined) {
59000             return this.getLayoutItems()[item || 0];
59001         }
59002         else {
59003             return this.owner.getComponent(item);
59004         }
59005     },
59006
59007     
59008     configureItem: function(item, position) {
59009         this.callParent([item, position]);
59010         if (this.hideInactive && this.activeItem !== item) {
59011             item.hide();
59012         }
59013         else {
59014             item.show();
59015         }
59016     },
59017
59018     onRemove: function(component) {
59019         if (component === this.activeItem) {
59020             this.activeItem = null;
59021             if (this.owner.items.getCount() === 0) {
59022                 this.firstActivated = false;
59023             }
59024         }
59025     },
59026
59027     
59028     getAnimation: function(newCard, owner) {
59029         var newAnim = (newCard || {}).cardSwitchAnimation;
59030         if (newAnim === false) {
59031             return false;
59032         }
59033         return newAnim || owner.cardSwitchAnimation;
59034     },
59035
59036     
59037     getNext: function() {
59038         
59039         
59040         var wrap = arguments[0];
59041         var items = this.getLayoutItems(),
59042             index = Ext.Array.indexOf(items, this.activeItem);
59043         return items[index + 1] || (wrap ? items[0] : false);
59044     },
59045
59046     
59047     next: function() {
59048         
59049         
59050         var anim = arguments[0], wrap = arguments[1];
59051         return this.setActiveItem(this.getNext(wrap), anim);
59052     },
59053
59054     
59055     getPrev: function() {
59056         
59057         
59058         var wrap = arguments[0];
59059         var items = this.getLayoutItems(),
59060             index = Ext.Array.indexOf(items, this.activeItem);
59061         return items[index - 1] || (wrap ? items[items.length - 1] : false);
59062     },
59063
59064     
59065     prev: function() {
59066         
59067         
59068         var anim = arguments[0], wrap = arguments[1];
59069         return this.setActiveItem(this.getPrev(wrap), anim);
59070     }
59071 });
59072
59073
59074 Ext.define('Ext.selection.Model', {
59075     extend: 'Ext.util.Observable',
59076     alternateClassName: 'Ext.AbstractSelectionModel',
59077     requires: ['Ext.data.StoreManager'],
59078     
59079
59080     
59081
59082     
59083     allowDeselect: false,
59084
59085     
59086     selected: null,
59087
59088     
59089     pruneRemoved: true,
59090
59091     constructor: function(cfg) {
59092         var me = this;
59093
59094         cfg = cfg || {};
59095         Ext.apply(me, cfg);
59096
59097         me.addEvents(
59098             
59099             'selectionchange'
59100         );
59101
59102         me.modes = {
59103             SINGLE: true,
59104             SIMPLE: true,
59105             MULTI: true
59106         };
59107
59108         
59109         me.setSelectionMode(cfg.mode || me.mode);
59110
59111         
59112         me.selected = Ext.create('Ext.util.MixedCollection');
59113
59114         me.callParent(arguments);
59115     },
59116
59117     
59118     bind : function(store, initial){
59119         var me = this;
59120
59121         if(!initial && me.store){
59122             if(store !== me.store && me.store.autoDestroy){
59123                 me.store.destroyStore();
59124             }else{
59125                 me.store.un("add", me.onStoreAdd, me);
59126                 me.store.un("clear", me.onStoreClear, me);
59127                 me.store.un("remove", me.onStoreRemove, me);
59128                 me.store.un("update", me.onStoreUpdate, me);
59129             }
59130         }
59131         if(store){
59132             store = Ext.data.StoreManager.lookup(store);
59133             store.on({
59134                 add: me.onStoreAdd,
59135                 clear: me.onStoreClear,
59136                 remove: me.onStoreRemove,
59137                 update: me.onStoreUpdate,
59138                 scope: me
59139             });
59140         }
59141         me.store = store;
59142         if(store && !initial) {
59143             me.refresh();
59144         }
59145     },
59146
59147     
59148     selectAll: function(suppressEvent) {
59149         var me = this,
59150             selections = me.store.getRange(),
59151             i = 0,
59152             len = selections.length,
59153             start = me.getSelection().length;
59154
59155         me.bulkChange = true;
59156         for (; i < len; i++) {
59157             me.doSelect(selections[i], true, suppressEvent);
59158         }
59159         delete me.bulkChange;
59160         
59161         me.maybeFireSelectionChange(me.getSelection().length !== start);
59162     },
59163
59164     
59165     deselectAll: function(suppressEvent) {
59166         var me = this,
59167             selections = me.getSelection(),
59168             i = 0,
59169             len = selections.length,
59170             start = me.getSelection().length;
59171
59172         me.bulkChange = true;
59173         for (; i < len; i++) {
59174             me.doDeselect(selections[i], suppressEvent);
59175         }
59176         delete me.bulkChange;
59177         
59178         me.maybeFireSelectionChange(me.getSelection().length !== start);
59179     },
59180
59181     
59182     
59183     
59184     selectWithEvent: function(record, e, keepExisting) {
59185         var me = this;
59186
59187         switch (me.selectionMode) {
59188             case 'MULTI':
59189                 if (e.ctrlKey && me.isSelected(record)) {
59190                     me.doDeselect(record, false);
59191                 } else if (e.shiftKey && me.lastFocused) {
59192                     me.selectRange(me.lastFocused, record, e.ctrlKey);
59193                 } else if (e.ctrlKey) {
59194                     me.doSelect(record, true, false);
59195                 } else if (me.isSelected(record) && !e.shiftKey && !e.ctrlKey && me.selected.getCount() > 1) {
59196                     me.doSelect(record, keepExisting, false);
59197                 } else {
59198                     me.doSelect(record, false);
59199                 }
59200                 break;
59201             case 'SIMPLE':
59202                 if (me.isSelected(record)) {
59203                     me.doDeselect(record);
59204                 } else {
59205                     me.doSelect(record, true);
59206                 }
59207                 break;
59208             case 'SINGLE':
59209                 
59210                 if (me.allowDeselect && me.isSelected(record)) {
59211                     me.doDeselect(record);
59212                 
59213                 } else {
59214                     me.doSelect(record, false);
59215                 }
59216                 break;
59217         }
59218     },
59219
59220     
59221     selectRange : function(startRow, endRow, keepExisting, dir){
59222         var me = this,
59223             store = me.store,
59224             selectedCount = 0,
59225             i,
59226             tmp,
59227             dontDeselect,
59228             records = [];
59229
59230         if (me.isLocked()){
59231             return;
59232         }
59233
59234         if (!keepExisting) {
59235             me.deselectAll(true);
59236         }
59237
59238         if (!Ext.isNumber(startRow)) {
59239             startRow = store.indexOf(startRow);
59240         }
59241         if (!Ext.isNumber(endRow)) {
59242             endRow = store.indexOf(endRow);
59243         }
59244
59245         
59246         if (startRow > endRow){
59247             tmp = endRow;
59248             endRow = startRow;
59249             startRow = tmp;
59250         }
59251
59252         for (i = startRow; i <= endRow; i++) {
59253             if (me.isSelected(store.getAt(i))) {
59254                 selectedCount++;
59255             }
59256         }
59257
59258         if (!dir) {
59259             dontDeselect = -1;
59260         } else {
59261             dontDeselect = (dir == 'up') ? startRow : endRow;
59262         }
59263
59264         for (i = startRow; i <= endRow; i++){
59265             if (selectedCount == (endRow - startRow + 1)) {
59266                 if (i != dontDeselect) {
59267                     me.doDeselect(i, true);
59268                 }
59269             } else {
59270                 records.push(store.getAt(i));
59271             }
59272         }
59273         me.doMultiSelect(records, true);
59274     },
59275
59276     
59277     select: function(records, keepExisting, suppressEvent) {
59278         
59279         if (Ext.isDefined(records)) {
59280             this.doSelect(records, keepExisting, suppressEvent);
59281         }
59282     },
59283
59284     
59285     deselect: function(records, suppressEvent) {
59286         this.doDeselect(records, suppressEvent);
59287     },
59288
59289     doSelect: function(records, keepExisting, suppressEvent) {
59290         var me = this,
59291             record;
59292
59293         if (me.locked) {
59294             return;
59295         }
59296         if (typeof records === "number") {
59297             records = [me.store.getAt(records)];
59298         }
59299         if (me.selectionMode == "SINGLE" && records) {
59300             record = records.length ? records[0] : records;
59301             me.doSingleSelect(record, suppressEvent);
59302         } else {
59303             me.doMultiSelect(records, keepExisting, suppressEvent);
59304         }
59305     },
59306
59307     doMultiSelect: function(records, keepExisting, suppressEvent) {
59308         var me = this,
59309             selected = me.selected,
59310             change = false,
59311             i = 0,
59312             len, record;
59313
59314         if (me.locked) {
59315             return;
59316         }
59317
59318
59319         records = !Ext.isArray(records) ? [records] : records;
59320         len = records.length;
59321         if (!keepExisting && selected.getCount() > 0) {
59322             if (me.doDeselect(me.getSelection(), suppressEvent) === false) {
59323                 return;
59324             }
59325             
59326         }
59327
59328         function commit () {
59329             selected.add(record);
59330             change = true;
59331         }
59332
59333         for (; i < len; i++) {
59334             record = records[i];
59335             if (keepExisting && me.isSelected(record)) {
59336                 continue;
59337             }
59338             me.lastSelected = record;
59339
59340             me.onSelectChange(record, true, suppressEvent, commit);
59341         }
59342         me.setLastFocused(record, suppressEvent);
59343         
59344         me.maybeFireSelectionChange(change && !suppressEvent);
59345     },
59346
59347     
59348     doDeselect: function(records, suppressEvent) {
59349         var me = this,
59350             selected = me.selected,
59351             i = 0,
59352             len, record,
59353             attempted = 0,
59354             accepted = 0;
59355
59356         if (me.locked) {
59357             return false;
59358         }
59359
59360         if (typeof records === "number") {
59361             records = [me.store.getAt(records)];
59362         } else if (!Ext.isArray(records)) {
59363             records = [records];
59364         }
59365
59366         function commit () {
59367             ++accepted;
59368             selected.remove(record);
59369         }
59370
59371         len = records.length;
59372
59373         for (; i < len; i++) {
59374             record = records[i];
59375             if (me.isSelected(record)) {
59376                 if (me.lastSelected == record) {
59377                     me.lastSelected = selected.last();
59378                 }
59379                 ++attempted;
59380                 me.onSelectChange(record, false, suppressEvent, commit);
59381             }
59382         }
59383
59384         
59385         me.maybeFireSelectionChange(accepted > 0 && !suppressEvent);
59386         return accepted === attempted;
59387     },
59388
59389     doSingleSelect: function(record, suppressEvent) {
59390         var me = this,
59391             changed = false,
59392             selected = me.selected;
59393
59394         if (me.locked) {
59395             return;
59396         }
59397         
59398         
59399         if (me.isSelected(record)) {
59400             return;
59401         }
59402
59403         function commit () {
59404             me.bulkChange = true;
59405             if (selected.getCount() > 0 && me.doDeselect(me.lastSelected, suppressEvent) === false) {
59406                 delete me.bulkChange;
59407                 return false;
59408             }
59409             delete me.bulkChange;
59410
59411             selected.add(record);
59412             me.lastSelected = record;
59413             changed = true;
59414         }
59415
59416         me.onSelectChange(record, true, suppressEvent, commit);
59417
59418         if (changed) {
59419             if (!suppressEvent) {
59420                 me.setLastFocused(record);
59421             }
59422             me.maybeFireSelectionChange(!suppressEvent);
59423         }
59424     },
59425
59426     
59427     setLastFocused: function(record, supressFocus) {
59428         var me = this,
59429             recordBeforeLast = me.lastFocused;
59430         me.lastFocused = record;
59431         me.onLastFocusChanged(recordBeforeLast, record, supressFocus);
59432     },
59433
59434     
59435     isFocused: function(record) {
59436         return record === this.getLastFocused();
59437     },
59438
59439
59440     
59441     
59442     maybeFireSelectionChange: function(fireEvent) {
59443         var me = this;
59444         if (fireEvent && !me.bulkChange) {
59445             me.fireEvent('selectionchange', me, me.getSelection());
59446         }
59447     },
59448
59449     
59450     getLastSelected: function() {
59451         return this.lastSelected;
59452     },
59453
59454     getLastFocused: function() {
59455         return this.lastFocused;
59456     },
59457
59458     
59459     getSelection: function() {
59460         return this.selected.getRange();
59461     },
59462
59463     
59464     getSelectionMode: function() {
59465         return this.selectionMode;
59466     },
59467
59468     
59469     setSelectionMode: function(selMode) {
59470         selMode = selMode ? selMode.toUpperCase() : 'SINGLE';
59471         
59472         
59473         this.selectionMode = this.modes[selMode] ? selMode : 'SINGLE';
59474     },
59475
59476     
59477     isLocked: function() {
59478         return this.locked;
59479     },
59480
59481     
59482     setLocked: function(locked) {
59483         this.locked = !!locked;
59484     },
59485
59486     
59487     isSelected: function(record) {
59488         record = Ext.isNumber(record) ? this.store.getAt(record) : record;
59489         return this.selected.indexOf(record) !== -1;
59490     },
59491
59492     
59493     hasSelection: function() {
59494         return this.selected.getCount() > 0;
59495     },
59496
59497     refresh: function() {
59498         var me = this,
59499             toBeSelected = [],
59500             oldSelections = me.getSelection(),
59501             len = oldSelections.length,
59502             selection,
59503             change,
59504             i = 0,
59505             lastFocused = this.getLastFocused();
59506
59507         
59508         
59509         
59510         for (; i < len; i++) {
59511             selection = oldSelections[i];
59512             if (!this.pruneRemoved || me.store.indexOf(selection) !== -1) {
59513                 toBeSelected.push(selection);
59514             }
59515         }
59516
59517         
59518         
59519         if (me.selected.getCount() != toBeSelected.length) {
59520             change = true;
59521         }
59522
59523         me.clearSelections();
59524
59525         if (me.store.indexOf(lastFocused) !== -1) {
59526             
59527             this.setLastFocused(lastFocused, true);
59528         }
59529
59530         if (toBeSelected.length) {
59531             
59532             me.doSelect(toBeSelected, false, true);
59533         }
59534
59535         me.maybeFireSelectionChange(change);
59536     },
59537
59538     
59539     clearSelections: function() {
59540         
59541         this.selected.clear();
59542         this.lastSelected = null;
59543         this.setLastFocused(null);
59544     },
59545
59546     
59547     onStoreAdd: function() {
59548
59549     },
59550
59551     
59552     
59553     onStoreClear: function() {
59554         if (this.selected.getCount > 0) {
59555             this.clearSelections();
59556             this.maybeFireSelectionChange(true);
59557         }
59558     },
59559
59560     
59561     
59562     
59563     onStoreRemove: function(store, record) {
59564         var me = this,
59565             selected = me.selected;
59566
59567         if (me.locked || !me.pruneRemoved) {
59568             return;
59569         }
59570
59571         if (selected.remove(record)) {
59572             if (me.lastSelected == record) {
59573                 me.lastSelected = null;
59574             }
59575             if (me.getLastFocused() == record) {
59576                 me.setLastFocused(null);
59577             }
59578             me.maybeFireSelectionChange(true);
59579         }
59580     },
59581
59582     
59583     getCount: function() {
59584         return this.selected.getCount();
59585     },
59586
59587     
59588     destroy: function() {
59589
59590     },
59591
59592     
59593     onStoreUpdate: function() {
59594
59595     },
59596
59597     
59598     onSelectChange: function(record, isSelected, suppressEvent) {
59599
59600     },
59601
59602     
59603     onLastFocusChanged: function(oldFocused, newFocused) {
59604
59605     },
59606
59607     
59608     onEditorKey: function(field, e) {
59609
59610     },
59611
59612     
59613     bindComponent: function(cmp) {
59614
59615     }
59616 });
59617
59618 Ext.define('Ext.selection.DataViewModel', {
59619     extend: 'Ext.selection.Model',
59620
59621     requires: ['Ext.util.KeyNav'],
59622
59623     deselectOnContainerClick: true,
59624
59625     
59626     enableKeyNav: true,
59627
59628     constructor: function(cfg){
59629         this.addEvents(
59630             
59631             'beforedeselect',
59632
59633             
59634             'beforeselect',
59635
59636             
59637             'deselect',
59638
59639             
59640             'select'
59641         );
59642         this.callParent(arguments);
59643     },
59644
59645     bindComponent: function(view) {
59646         var me = this,
59647             eventListeners = {
59648                 refresh: me.refresh,
59649                 scope: me
59650             };
59651
59652         me.view = view;
59653         me.bind(view.getStore());
59654
59655         view.on(view.triggerEvent, me.onItemClick, me);
59656         view.on(view.triggerCtEvent, me.onContainerClick, me);
59657
59658         view.on(eventListeners);
59659
59660         if (me.enableKeyNav) {
59661             me.initKeyNav(view);
59662         }
59663     },
59664
59665     onItemClick: function(view, record, item, index, e) {
59666         this.selectWithEvent(record, e);
59667     },
59668
59669     onContainerClick: function() {
59670         if (this.deselectOnContainerClick) {
59671             this.deselectAll();
59672         }
59673     },
59674
59675     initKeyNav: function(view) {
59676         var me = this;
59677
59678         if (!view.rendered) {
59679             view.on('render', Ext.Function.bind(me.initKeyNav, me, [view], 0), me, {single: true});
59680             return;
59681         }
59682
59683         view.el.set({
59684             tabIndex: -1
59685         });
59686         me.keyNav = Ext.create('Ext.util.KeyNav', view.el, {
59687             down: Ext.pass(me.onNavKey, [1], me),
59688             right: Ext.pass(me.onNavKey, [1], me),
59689             left: Ext.pass(me.onNavKey, [-1], me),
59690             up: Ext.pass(me.onNavKey, [-1], me),
59691             scope: me
59692         });
59693     },
59694
59695     onNavKey: function(step) {
59696         step = step || 1;
59697         var me = this,
59698             view = me.view,
59699             selected = me.getSelection()[0],
59700             numRecords = me.view.store.getCount(),
59701             idx;
59702
59703         if (selected) {
59704             idx = view.indexOf(view.getNode(selected)) + step;
59705         } else {
59706             idx = 0;
59707         }
59708
59709         if (idx < 0) {
59710             idx = numRecords - 1;
59711         } else if (idx >= numRecords) {
59712             idx = 0;
59713         }
59714
59715         me.select(idx);
59716     },
59717
59718     
59719     onSelectChange: function(record, isSelected, suppressEvent, commitFn) {
59720         var me = this,
59721             view = me.view,
59722             eventName = isSelected ? 'select' : 'deselect';
59723
59724         if ((suppressEvent || me.fireEvent('before' + eventName, me, record)) !== false &&
59725                 commitFn() !== false) {
59726
59727             if (isSelected) {
59728                 view.onItemSelect(record);
59729             } else {
59730                 view.onItemDeselect(record);
59731             }
59732
59733             if (!suppressEvent) {
59734                 me.fireEvent(eventName, me, record);
59735             }
59736         }
59737     },
59738     
59739     destroy: function(){
59740         Ext.destroy(this.keyNav);
59741         this.callParent();
59742     }
59743 });
59744
59745
59746 Ext.define('Ext.state.CookieProvider', {
59747     extend: 'Ext.state.Provider',
59748
59749     
59750
59751     
59752
59753     
59754
59755     
59756
59757     
59758     constructor : function(config){
59759         var me = this;
59760         me.path = "/";
59761         me.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); 
59762         me.domain = null;
59763         me.secure = false;
59764         me.callParent(arguments);
59765         me.state = me.readCookies();
59766     },
59767
59768     
59769     set : function(name, value){
59770         var me = this;
59771
59772         if(typeof value == "undefined" || value === null){
59773             me.clear(name);
59774             return;
59775         }
59776         me.setCookie(name, value);
59777         me.callParent(arguments);
59778     },
59779
59780     
59781     clear : function(name){
59782         this.clearCookie(name);
59783         this.callParent(arguments);
59784     },
59785
59786     
59787     readCookies : function(){
59788         var cookies = {},
59789             c = document.cookie + ";",
59790             re = /\s?(.*?)=(.*?);/g,
59791             prefix = this.prefix,
59792             len = prefix.length,
59793             matches,
59794             name,
59795             value;
59796
59797         while((matches = re.exec(c)) != null){
59798             name = matches[1];
59799             value = matches[2];
59800             if (name && name.substring(0, len) == prefix){
59801                 cookies[name.substr(len)] = this.decodeValue(value);
59802             }
59803         }
59804         return cookies;
59805     },
59806
59807     
59808     setCookie : function(name, value){
59809         var me = this;
59810
59811         document.cookie = me.prefix + name + "=" + me.encodeValue(value) +
59812            ((me.expires == null) ? "" : ("; expires=" + me.expires.toGMTString())) +
59813            ((me.path == null) ? "" : ("; path=" + me.path)) +
59814            ((me.domain == null) ? "" : ("; domain=" + me.domain)) +
59815            ((me.secure == true) ? "; secure" : "");
59816     },
59817
59818     
59819     clearCookie : function(name){
59820         var me = this;
59821
59822         document.cookie = me.prefix + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
59823            ((me.path == null) ? "" : ("; path=" + me.path)) +
59824            ((me.domain == null) ? "" : ("; domain=" + me.domain)) +
59825            ((me.secure == true) ? "; secure" : "");
59826     }
59827 });
59828
59829
59830
59831 Ext.define('Ext.state.LocalStorageProvider', {
59832     
59833     
59834     extend: 'Ext.state.Provider',
59835     
59836     alias: 'state.localstorage',
59837     
59838     
59839    
59840     constructor: function(){
59841         var me = this;
59842         me.callParent(arguments);
59843         me.store = me.getStorageObject();
59844         me.state = me.readLocalStorage();
59845     },
59846     
59847     readLocalStorage: function(){
59848         var store = this.store,
59849             i = 0,
59850             len = store.length,
59851             prefix = this.prefix,
59852             prefixLen = prefix.length,
59853             data = {},
59854             key;
59855             
59856         for (; i < len; ++i) {
59857             key = store.key(i);
59858             if (key.substring(0, prefixLen) == prefix) {
59859                 data[key.substr(prefixLen)] = this.decodeValue(store.getItem(key));
59860             }            
59861         }
59862         return data;
59863     },
59864     
59865     set : function(name, value){
59866         var me = this;
59867         
59868         me.clear(name);
59869         if (typeof value == "undefined" || value === null) {
59870             return;
59871         }
59872         me.store.setItem(me.prefix + name, me.encodeValue(value));
59873         me.callParent(arguments);
59874     },
59875
59876     
59877     clear : function(name){
59878         this.store.removeItem(this.prefix + name);
59879         this.callParent(arguments);
59880     },
59881     
59882     getStorageObject: function(){
59883         try {
59884             var supports = 'localStorage' in window && window['localStorage'] !== null;
59885             if (supports) {
59886                 return window.localStorage;
59887             }
59888         } catch (e) {
59889             return false;
59890         }
59891     }    
59892 });
59893
59894
59895 Ext.define('Ext.util.Point', {
59896
59897     
59898     extend: 'Ext.util.Region',
59899
59900     statics: {
59901
59902         
59903         fromEvent: function(e) {
59904             e = (e.changedTouches && e.changedTouches.length > 0) ? e.changedTouches[0] : e;
59905             return new this(e.pageX, e.pageY);
59906         }
59907     },
59908
59909     
59910
59911     
59912     constructor: function(x, y) {
59913         this.callParent([y, x, y, x]);
59914     },
59915
59916     
59917     toString: function() {
59918         return "Point[" + this.x + "," + this.y + "]";
59919     },
59920
59921     
59922     equals: function(p) {
59923         return (this.x == p.x && this.y == p.y);
59924     },
59925
59926     
59927     isWithin: function(p, threshold) {
59928         if (!Ext.isObject(threshold)) {
59929             threshold = {
59930                 x: threshold,
59931                 y: threshold
59932             };
59933         }
59934
59935         return (this.x <= p.x + threshold.x && this.x >= p.x - threshold.x &&
59936                 this.y <= p.y + threshold.y && this.y >= p.y - threshold.y);
59937     },
59938
59939     
59940     roundedEquals: function(p) {
59941         return (Math.round(this.x) == Math.round(p.x) && Math.round(this.y) == Math.round(p.y));
59942     }
59943 }, function() {
59944     
59945     this.prototype.translate = Ext.util.Region.prototype.translateBy;
59946 });
59947
59948
59949
59950 Ext.define('Ext.LoadMask', {
59951
59952     extend: 'Ext.Component',
59953
59954     alias: 'widget.loadmask',
59955
59956     
59957
59958     mixins: {
59959         floating: 'Ext.util.Floating'
59960     },
59961
59962     uses: ['Ext.data.StoreManager'],
59963
59964     
59965
59966     
59967
59968     
59969     msg : 'Loading...',
59970     
59971     msgCls : Ext.baseCSSPrefix + 'mask-loading',
59972     
59973     
59974     useMsg: true,
59975
59976     
59977     disabled: false,
59978
59979     baseCls: Ext.baseCSSPrefix + 'mask-msg',
59980
59981     renderTpl: '<div style="position:relative" class="{msgCls}"></div>',
59982
59983     
59984     modal: true,
59985
59986     
59987     floating: {
59988         shadow: 'frame'
59989     },
59990
59991     
59992     focusOnToFront: false,
59993
59994     
59995     constructor : function(el, config) {
59996         var me = this;
59997
59998         
59999         if (el.isComponent) {
60000             me.ownerCt = el;
60001             me.bindComponent(el);
60002         }
60003         
60004         else {
60005             me.ownerCt = new Ext.Component({
60006                 el: Ext.get(el),
60007                 rendered: true,
60008                 componentLayoutCounter: 1
60009             });
60010             me.container = el;
60011         }
60012         me.callParent([config]);
60013
60014         if (me.store) {
60015             me.bindStore(me.store, true);
60016         }
60017         me.renderData = {
60018             msgCls: me.msgCls
60019         };
60020         me.renderSelectors = {
60021             msgEl: 'div'
60022         };
60023     },
60024
60025     bindComponent: function(comp) {
60026         this.mon(comp, {
60027             resize: this.onComponentResize,
60028             scope: this
60029         });
60030     },
60031
60032     afterRender: function() {
60033         this.callParent(arguments);
60034         this.container = this.floatParent.getContentTarget();
60035     },
60036
60037     
60038     onComponentResize: function() {
60039         var me = this;
60040         if (me.rendered && me.isVisible()) {
60041             me.toFront();
60042             me.center();
60043         }
60044     },
60045
60046     
60047     bindStore : function(store, initial) {
60048         var me = this;
60049
60050         if (!initial && me.store) {
60051             me.mun(me.store, {
60052                 scope: me,
60053                 beforeload: me.onBeforeLoad,
60054                 load: me.onLoad,
60055                 exception: me.onLoad
60056             });
60057             if (!store) {
60058                 me.store = null;
60059             }
60060         }
60061         if (store) {
60062             store = Ext.data.StoreManager.lookup(store);
60063             me.mon(store, {
60064                 scope: me,
60065                 beforeload: me.onBeforeLoad,
60066                 load: me.onLoad,
60067                 exception: me.onLoad
60068             });
60069
60070         }
60071         me.store = store;
60072         if (store && store.isLoading()) {
60073             me.onBeforeLoad();
60074         }
60075     },
60076
60077     onDisable : function() {
60078         this.callParent(arguments);
60079         if (this.loading) {
60080             this.onLoad();
60081         }
60082     },
60083
60084     
60085     onBeforeLoad : function() {
60086         var me = this,
60087             owner = me.ownerCt || me.floatParent,
60088             origin;
60089         if (!this.disabled) {
60090             
60091             
60092             if (owner.componentLayoutCounter) {
60093                 Ext.Component.prototype.show.call(me);
60094             } else {
60095                 
60096                 origin = owner.afterComponentLayout;
60097                 owner.afterComponentLayout = function() {
60098                     owner.afterComponentLayout = origin;
60099                     origin.apply(owner, arguments);
60100                     if(me.loading) {
60101                         Ext.Component.prototype.show.call(me);
60102                     }
60103                 };
60104             }
60105         }
60106     },
60107
60108     onHide: function(){
60109         var me = this;
60110         me.callParent(arguments);
60111         me.showOnParentShow = true;
60112     },
60113
60114     onShow: function() {
60115         var me = this,
60116             msgEl = me.msgEl;
60117             
60118         me.callParent(arguments);
60119         me.loading = true;
60120         if (me.useMsg) {
60121             msgEl.show().update(me.msg);
60122         } else {
60123             msgEl.parent().hide();
60124         }
60125     },
60126
60127     afterShow: function() {
60128         this.callParent(arguments);
60129         this.center();
60130     },
60131
60132     
60133     onLoad : function() {
60134         this.loading = false;
60135         Ext.Component.prototype.hide.call(this);
60136     }
60137 });
60138
60139 Ext.define('Ext.view.AbstractView', {
60140     extend: 'Ext.Component',
60141     alternateClassName: 'Ext.view.AbstractView',
60142     requires: [
60143         'Ext.LoadMask',
60144         'Ext.data.StoreManager',
60145         'Ext.CompositeElementLite',
60146         'Ext.DomQuery',
60147         'Ext.selection.DataViewModel'
60148     ],
60149
60150     inheritableStatics: {
60151         getRecord: function(node) {
60152             return this.getBoundView(node).getRecord(node);
60153         },
60154
60155         getBoundView: function(node) {
60156             return Ext.getCmp(node.boundView);
60157         }
60158     },
60159
60160     
60161     
60162
60163     
60164     deferInitialRefresh: true,
60165
60166     
60167
60168     
60169     itemCls: Ext.baseCSSPrefix + 'dataview-item',
60170
60171     
60172
60173     
60174
60175     
60176     loadingText: 'Loading...',
60177
60178     
60179     loadMask: true,
60180
60181     
60182
60183     
60184     loadingUseMsg: true,
60185
60186
60187     
60188
60189     
60190     selectedItemCls: Ext.baseCSSPrefix + 'item-selected',
60191
60192     
60193     emptyText: "",
60194
60195     
60196     deferEmptyText: true,
60197
60198     
60199     trackOver: false,
60200
60201     
60202     blockRefresh: false,
60203
60204     
60205
60206
60207     
60208     last: false,
60209
60210     triggerEvent: 'itemclick',
60211     triggerCtEvent: 'containerclick',
60212
60213     addCmpEvents: function() {
60214
60215     },
60216
60217     
60218     initComponent : function(){
60219         var me = this,
60220             isDef = Ext.isDefined,
60221             itemTpl = me.itemTpl,
60222             memberFn = {};
60223
60224         if (itemTpl) {
60225             if (Ext.isArray(itemTpl)) {
60226                 
60227                 itemTpl = itemTpl.join('');
60228             } else if (Ext.isObject(itemTpl)) {
60229                 
60230                 memberFn = Ext.apply(memberFn, itemTpl.initialConfig);
60231                 itemTpl = itemTpl.html;
60232             }
60233
60234             if (!me.itemSelector) {
60235                 me.itemSelector = '.' + me.itemCls;
60236             }
60237
60238             itemTpl = Ext.String.format('<tpl for="."><div class="{0}">{1}</div></tpl>', me.itemCls, itemTpl);
60239             me.tpl = Ext.create('Ext.XTemplate', itemTpl, memberFn);
60240         }
60241
60242
60243         me.callParent();
60244         if(Ext.isString(me.tpl) || Ext.isArray(me.tpl)){
60245             me.tpl = Ext.create('Ext.XTemplate', me.tpl);
60246         }
60247
60248
60249         me.addEvents(
60250             
60251             'beforerefresh',
60252             
60253             'refresh',
60254             
60255             'viewready',
60256             
60257             'itemupdate',
60258             
60259             'itemadd',
60260             
60261             'itemremove'
60262         );
60263
60264         me.addCmpEvents();
60265
60266         
60267         me.store = Ext.data.StoreManager.lookup(me.store || 'ext-empty-store');
60268         me.all = new Ext.CompositeElementLite();
60269     },
60270
60271     onRender: function() {
60272         var me = this,
60273             mask = me.loadMask,
60274             cfg = {
60275                 msg: me.loadingText,
60276                 msgCls: me.loadingCls,
60277                 useMsg: me.loadingUseMsg
60278             };
60279
60280         me.callParent(arguments);
60281
60282         if (mask) {
60283             
60284             if (Ext.isObject(mask)) {
60285                 cfg = Ext.apply(cfg, mask);
60286             }
60287             
60288             
60289             
60290             
60291             me.loadMask = Ext.create('Ext.LoadMask', me, cfg);
60292             me.loadMask.on({
60293                 scope: me,
60294                 beforeshow: me.onMaskBeforeShow,
60295                 hide: me.onMaskHide
60296             });
60297         }
60298     },
60299
60300     onMaskBeforeShow: function(){
60301         var loadingHeight = this.loadingHeight;
60302         
60303         this.getSelectionModel().deselectAll();
60304         if (loadingHeight) {
60305             this.setCalculatedSize(undefined, loadingHeight);
60306         }
60307     },
60308
60309     onMaskHide: function(){
60310         var me = this;
60311         
60312         if (!me.destroying && me.loadingHeight) {
60313             me.setHeight(me.height);
60314         }
60315     },
60316
60317     afterRender: function() {
60318         this.callParent(arguments);
60319
60320         
60321         
60322         
60323         this.getSelectionModel().bindComponent(this);
60324     },
60325
60326     
60327     getSelectionModel: function(){
60328         var me = this,
60329             mode = 'SINGLE';
60330
60331         if (!me.selModel) {
60332             me.selModel = {};
60333         }
60334
60335         if (me.simpleSelect) {
60336             mode = 'SIMPLE';
60337         } else if (me.multiSelect) {
60338             mode = 'MULTI';
60339         }
60340
60341         Ext.applyIf(me.selModel, {
60342             allowDeselect: me.allowDeselect,
60343             mode: mode
60344         });
60345
60346         if (!me.selModel.events) {
60347             me.selModel = Ext.create('Ext.selection.DataViewModel', me.selModel);
60348         }
60349
60350         if (!me.selModel.hasRelaySetup) {
60351             me.relayEvents(me.selModel, [
60352                 'selectionchange', 'beforeselect', 'beforedeselect', 'select', 'deselect'
60353             ]);
60354             me.selModel.hasRelaySetup = true;
60355         }
60356
60357         
60358         
60359         if (me.disableSelection) {
60360             me.selModel.locked = true;
60361         }
60362
60363         return me.selModel;
60364     },
60365
60366     
60367     refresh: function() {
60368         var me = this,
60369             el,
60370             records;
60371
60372         if (!me.rendered || me.isDestroyed) {
60373             return;
60374         }
60375
60376         me.fireEvent('beforerefresh', me);
60377         el = me.getTargetEl();
60378         records = me.store.getRange();
60379
60380         el.update('');
60381         if (records.length < 1) {
60382             if (!me.deferEmptyText || me.hasSkippedEmptyText) {
60383                 el.update(me.emptyText);
60384             }
60385             me.all.clear();
60386         } else {
60387             me.tpl.overwrite(el, me.collectData(records, 0));
60388             me.all.fill(Ext.query(me.getItemSelector(), el.dom));
60389             me.updateIndexes(0);
60390         }
60391
60392         me.selModel.refresh();
60393         me.hasSkippedEmptyText = true;
60394         me.fireEvent('refresh', me);
60395
60396         
60397         
60398         if (!me.viewReady) {
60399             
60400             
60401             me.viewReady = true;
60402             me.fireEvent('viewready', me);
60403         }
60404     },
60405
60406     
60407     prepareData: function(data, index, record) {
60408         if (record) {
60409             Ext.apply(data, record.getAssociatedData());
60410         }
60411         return data;
60412     },
60413
60414     
60415     collectData : function(records, startIndex){
60416         var r = [],
60417             i = 0,
60418             len = records.length,
60419             record;
60420
60421         for(; i < len; i++){
60422             record = records[i];
60423             r[r.length] = this.prepareData(record[record.persistenceProperty], startIndex + i, record);
60424         }
60425         return r;
60426     },
60427
60428     
60429     bufferRender : function(records, index){
60430         var div = document.createElement('div');
60431         this.tpl.overwrite(div, this.collectData(records, index));
60432         return Ext.query(this.getItemSelector(), div);
60433     },
60434
60435     
60436     onUpdate : function(ds, record){
60437         var me = this,
60438             index = me.store.indexOf(record),
60439             node;
60440
60441         if (index > -1){
60442             node = me.bufferRender([record], index)[0];
60443             
60444             if (me.getNode(record)) {
60445                 me.all.replaceElement(index, node, true);
60446                 me.updateIndexes(index, index);
60447                 
60448                 
60449                 me.selModel.refresh();
60450                 me.fireEvent('itemupdate', record, index, node);
60451             }
60452         }
60453
60454     },
60455
60456     
60457     onAdd : function(ds, records, index) {
60458         var me = this,
60459             nodes;
60460
60461         if (me.all.getCount() === 0) {
60462             me.refresh();
60463             return;
60464         }
60465
60466         nodes = me.bufferRender(records, index);
60467         me.doAdd(nodes, records, index);
60468
60469         me.selModel.refresh();
60470         me.updateIndexes(index);
60471         me.fireEvent('itemadd', records, index, nodes);
60472     },
60473
60474     doAdd: function(nodes, records, index) {
60475         var all = this.all;
60476
60477         if (index < all.getCount()) {
60478             all.item(index).insertSibling(nodes, 'before', true);
60479         } else {
60480             all.last().insertSibling(nodes, 'after', true);
60481         }
60482
60483         Ext.Array.insert(all.elements, index, nodes);
60484     },
60485
60486     
60487     onRemove : function(ds, record, index) {
60488         var me = this;
60489
60490         me.doRemove(record, index);
60491         me.updateIndexes(index);
60492         if (me.store.getCount() === 0){
60493             me.refresh();
60494         }
60495         me.fireEvent('itemremove', record, index);
60496     },
60497
60498     doRemove: function(record, index) {
60499         this.all.removeElement(index, true);
60500     },
60501
60502     
60503     refreshNode : function(index){
60504         this.onUpdate(this.store, this.store.getAt(index));
60505     },
60506
60507     
60508     updateIndexes : function(startIndex, endIndex) {
60509         var ns = this.all.elements,
60510             records = this.store.getRange(),
60511             i;
60512             
60513         startIndex = startIndex || 0;
60514         endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length - 1));
60515         for(i = startIndex; i <= endIndex; i++){
60516             ns[i].viewIndex = i;
60517             ns[i].viewRecordId = records[i].internalId;
60518             if (!ns[i].boundView) {
60519                 ns[i].boundView = this.id;
60520             }
60521         }
60522     },
60523
60524     
60525     getStore : function(){
60526         return this.store;
60527     },
60528
60529     
60530     bindStore : function(store, initial) {
60531         var me = this,
60532             maskStore;
60533
60534         if (!initial && me.store) {
60535             if (store !== me.store && me.store.autoDestroy) {
60536                 me.store.destroyStore();
60537             }
60538             else {
60539                 me.mun(me.store, {
60540                     scope: me,
60541                     datachanged: me.onDataChanged,
60542                     add: me.onAdd,
60543                     remove: me.onRemove,
60544                     update: me.onUpdate,
60545                     clear: me.refresh
60546                 });
60547             }
60548             if (!store) {
60549                 
60550                 if (me.loadMask && me.loadMask.bindStore) {
60551                     me.loadMask.bindStore(null);
60552                 }
60553                 me.store = null;
60554             }
60555         }
60556         if (store) {
60557             store = Ext.data.StoreManager.lookup(store);
60558             me.mon(store, {
60559                 scope: me,
60560                 datachanged: me.onDataChanged,
60561                 add: me.onAdd,
60562                 remove: me.onRemove,
60563                 update: me.onUpdate,
60564                 clear: me.refresh
60565             });
60566             
60567             if (me.loadMask && me.loadMask.bindStore) {
60568                 
60569                 if (Ext.Array.contains(store.alias, 'store.node')) {
60570                     maskStore = this.ownerCt.store;
60571                 } else {
60572                     maskStore = store;
60573                 }
60574                 me.loadMask.bindStore(maskStore);
60575             }
60576         }
60577
60578         
60579         
60580         me.viewReady = false;
60581
60582         me.store = store;
60583         
60584         me.getSelectionModel().bind(store);
60585
60586         
60587         if (store) {
60588             if (initial && me.deferInitialRefresh) {
60589                 Ext.Function.defer(function () {
60590                     if (!me.isDestroyed) {
60591                         me.refresh(true);
60592                     }
60593                 }, 1);
60594             } else {
60595                 me.refresh(true);
60596             }
60597         }
60598     },
60599
60600     
60601     onDataChanged: function() {
60602         if (this.blockRefresh !== true) {
60603             this.refresh.apply(this, arguments);
60604         }
60605     },
60606
60607     
60608     findItemByChild: function(node){
60609         return Ext.fly(node).findParent(this.getItemSelector(), this.getTargetEl());
60610     },
60611
60612     
60613     findTargetByEvent: function(e) {
60614         return e.getTarget(this.getItemSelector(), this.getTargetEl());
60615     },
60616
60617
60618     
60619     getSelectedNodes: function(){
60620         var nodes   = [],
60621             records = this.selModel.getSelection(),
60622             ln = records.length,
60623             i  = 0;
60624
60625         for (; i < ln; i++) {
60626             nodes.push(this.getNode(records[i]));
60627         }
60628
60629         return nodes;
60630     },
60631
60632     
60633     getRecords: function(nodes) {
60634         var records = [],
60635             i = 0,
60636             len = nodes.length,
60637             data = this.store.data;
60638
60639         for (; i < len; i++) {
60640             records[records.length] = data.getByKey(nodes[i].viewRecordId);
60641         }
60642
60643         return records;
60644     },
60645
60646     
60647     getRecord: function(node){
60648         return this.store.data.getByKey(Ext.getDom(node).viewRecordId);
60649     },
60650
60651
60652     
60653     isSelected : function(node) {
60654         
60655         var r = this.getRecord(node);
60656         return this.selModel.isSelected(r);
60657     },
60658
60659     
60660     select: function(records, keepExisting, suppressEvent) {
60661         this.selModel.select(records, keepExisting, suppressEvent);
60662     },
60663
60664     
60665     deselect: function(records, suppressEvent) {
60666         this.selModel.deselect(records, suppressEvent);
60667     },
60668
60669     
60670     getNode : function(nodeInfo) {
60671         if (!this.rendered) {
60672             return null;
60673         }
60674         if (Ext.isString(nodeInfo)) {
60675             return document.getElementById(nodeInfo);
60676         }
60677         if (Ext.isNumber(nodeInfo)) {
60678             return this.all.elements[nodeInfo];
60679         }
60680         if (nodeInfo instanceof Ext.data.Model) {
60681             return this.getNodeByRecord(nodeInfo);
60682         }
60683         return nodeInfo; 
60684     },
60685
60686     
60687     getNodeByRecord: function(record) {
60688         var ns = this.all.elements,
60689             ln = ns.length,
60690             i = 0;
60691
60692         for (; i < ln; i++) {
60693             if (ns[i].viewRecordId === record.internalId) {
60694                 return ns[i];
60695             }
60696         }
60697
60698         return null;
60699     },
60700
60701     
60702     getNodes: function(start, end) {
60703         var ns = this.all.elements,
60704             nodes = [],
60705             i;
60706
60707         start = start || 0;
60708         end = !Ext.isDefined(end) ? Math.max(ns.length - 1, 0) : end;
60709         if (start <= end) {
60710             for (i = start; i <= end && ns[i]; i++) {
60711                 nodes.push(ns[i]);
60712             }
60713         } else {
60714             for (i = start; i >= end && ns[i]; i--) {
60715                 nodes.push(ns[i]);
60716             }
60717         }
60718         return nodes;
60719     },
60720
60721     
60722     indexOf: function(node) {
60723         node = this.getNode(node);
60724         if (Ext.isNumber(node.viewIndex)) {
60725             return node.viewIndex;
60726         }
60727         return this.all.indexOf(node);
60728     },
60729
60730     onDestroy : function() {
60731         var me = this;
60732
60733         me.all.clear();
60734         me.callParent();
60735         me.bindStore(null);
60736         me.selModel.destroy();
60737     },
60738
60739     
60740     onItemSelect: function(record) {
60741         var node = this.getNode(record);
60742         
60743         if (node) {
60744             Ext.fly(node).addCls(this.selectedItemCls);
60745         }
60746     },
60747
60748     
60749     onItemDeselect: function(record) {
60750         var node = this.getNode(record);
60751         
60752         if (node) {
60753             Ext.fly(node).removeCls(this.selectedItemCls);
60754         }
60755     },
60756
60757     getItemSelector: function() {
60758         return this.itemSelector;
60759     }
60760 }, function() {
60761     
60762     
60763     
60764     
60765     Ext.deprecate('extjs', '4.0', function() {
60766         Ext.view.AbstractView.override({
60767             
60768             
60769             
60770
60771             
60772             getSelectionCount : function(){
60773                 if (Ext.global.console) {
60774                     Ext.global.console.warn("DataView: getSelectionCount will be removed, please interact with the Ext.selection.DataViewModel");
60775                 }
60776                 return this.selModel.getSelection().length;
60777             },
60778
60779             
60780             getSelectedRecords : function(){
60781                 if (Ext.global.console) {
60782                     Ext.global.console.warn("DataView: getSelectedRecords will be removed, please interact with the Ext.selection.DataViewModel");
60783                 }
60784                 return this.selModel.getSelection();
60785             },
60786
60787             select: function(records, keepExisting, supressEvents) {
60788                 if (Ext.global.console) {
60789                     Ext.global.console.warn("DataView: select will be removed, please access select through a DataView's SelectionModel, ie: view.getSelectionModel().select()");
60790                 }
60791                 var sm = this.getSelectionModel();
60792                 return sm.select.apply(sm, arguments);
60793             },
60794
60795             clearSelections: function() {
60796                 if (Ext.global.console) {
60797                     Ext.global.console.warn("DataView: clearSelections will be removed, please access deselectAll through DataView's SelectionModel, ie: view.getSelectionModel().deselectAll()");
60798                 }
60799                 var sm = this.getSelectionModel();
60800                 return sm.deselectAll();
60801             }
60802         });
60803     });
60804 });
60805
60806
60807 Ext.define('Ext.Action', {
60808
60809     
60810
60811     
60812
60813     
60814     
60815     
60816     
60817     
60818     
60819     
60820
60821     
60822     constructor : function(config){
60823         this.initialConfig = config;
60824         this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
60825         this.items = [];
60826     },
60827
60828     
60829     isAction : true,
60830
60831     
60832     setText : function(text){
60833         this.initialConfig.text = text;
60834         this.callEach('setText', [text]);
60835     },
60836
60837     
60838     getText : function(){
60839         return this.initialConfig.text;
60840     },
60841
60842     
60843     setIconCls : function(cls){
60844         this.initialConfig.iconCls = cls;
60845         this.callEach('setIconCls', [cls]);
60846     },
60847
60848     
60849     getIconCls : function(){
60850         return this.initialConfig.iconCls;
60851     },
60852
60853     
60854     setDisabled : function(v){
60855         this.initialConfig.disabled = v;
60856         this.callEach('setDisabled', [v]);
60857     },
60858
60859     
60860     enable : function(){
60861         this.setDisabled(false);
60862     },
60863
60864     
60865     disable : function(){
60866         this.setDisabled(true);
60867     },
60868
60869     
60870     isDisabled : function(){
60871         return this.initialConfig.disabled;
60872     },
60873
60874     
60875     setHidden : function(v){
60876         this.initialConfig.hidden = v;
60877         this.callEach('setVisible', [!v]);
60878     },
60879
60880     
60881     show : function(){
60882         this.setHidden(false);
60883     },
60884
60885     
60886     hide : function(){
60887         this.setHidden(true);
60888     },
60889
60890     
60891     isHidden : function(){
60892         return this.initialConfig.hidden;
60893     },
60894
60895     
60896     setHandler : function(fn, scope){
60897         this.initialConfig.handler = fn;
60898         this.initialConfig.scope = scope;
60899         this.callEach('setHandler', [fn, scope]);
60900     },
60901
60902     
60903     each : function(fn, scope){
60904         Ext.each(this.items, fn, scope);
60905     },
60906
60907     
60908     callEach : function(fnName, args){
60909         var items = this.items,
60910             i = 0,
60911             len = items.length;
60912
60913         for(; i < len; i++){
60914             items[i][fnName].apply(items[i], args);
60915         }
60916     },
60917
60918     
60919     addComponent : function(comp){
60920         this.items.push(comp);
60921         comp.on('destroy', this.removeComponent, this);
60922     },
60923
60924     
60925     removeComponent : function(comp){
60926         Ext.Array.remove(this.items, comp);
60927     },
60928
60929     
60930     execute : function(){
60931         this.initialConfig.handler.apply(this.initialConfig.scope || Ext.global, arguments);
60932     }
60933 });
60934
60935
60936 Ext.define('Ext.layout.component.Editor', {
60937
60938     
60939
60940     alias: ['layout.editor'],
60941
60942     extend: 'Ext.layout.component.Component',
60943
60944     
60945
60946     onLayout: function(width, height) {
60947         var me = this,
60948             owner = me.owner,
60949             autoSize = owner.autoSize;
60950             
60951         if (autoSize === true) {
60952             autoSize = {
60953                 width: 'field',
60954                 height: 'field'    
60955             };
60956         }
60957         
60958         if (autoSize) {
60959             width = me.getDimension(owner, autoSize.width, 'Width', width);
60960             height = me.getDimension(owner, autoSize.height, 'Height', height);
60961         }
60962         me.setTargetSize(width, height);
60963         owner.field.setSize(width, height);
60964     },
60965     
60966     getDimension: function(owner, type, dimension, actual){
60967         var method = 'get' + dimension;
60968         switch (type) {
60969             case 'boundEl':
60970                 return owner.boundEl[method]();
60971             case 'field':
60972                 return owner.field[method]();
60973             default:
60974                 return actual;
60975         }
60976     }
60977 });
60978
60979 Ext.define('Ext.Editor', {
60980
60981     
60982
60983     extend: 'Ext.Component',
60984
60985     alias: 'widget.editor',
60986
60987     requires: ['Ext.layout.component.Editor'],
60988
60989     
60990
60991    componentLayout: 'editor',
60992
60993     
60994
60995     
60996     allowBlur: true,
60997
60998     
60999
61000     
61001     revertInvalid: true,
61002
61003     
61004
61005     
61006
61007     
61008     value : '',
61009
61010     
61011     alignment: 'c-c?',
61012
61013     
61014     offsets: [0, 0],
61015
61016     
61017     shadow : 'frame',
61018
61019     
61020     constrain : false,
61021
61022     
61023     swallowKeys : true,
61024
61025     
61026     completeOnEnter : true,
61027
61028     
61029     cancelOnEsc : true,
61030
61031     
61032     updateEl : false,
61033
61034     
61035
61036     
61037     hidden: true,
61038     baseCls: Ext.baseCSSPrefix + 'editor',
61039
61040     initComponent : function() {
61041         var me = this,
61042             field = me.field = Ext.ComponentManager.create(me.field, 'textfield');
61043
61044         Ext.apply(field, {
61045             inEditor: true,
61046             msgTarget: field.msgTarget == 'title' ? 'title' :  'qtip'
61047         });
61048         me.mon(field, {
61049             scope: me,
61050             blur: {
61051                 fn: me.onBlur,
61052                 
61053                 delay: 1
61054             },
61055             specialkey: me.onSpecialKey
61056         });
61057
61058         if (field.grow) {
61059             me.mon(field, 'autosize', me.onAutoSize,  me, {delay: 1});
61060         }
61061         me.floating = {
61062             constrain: me.constrain
61063         };
61064
61065         me.callParent(arguments);
61066
61067         me.addEvents(
61068             
61069             'beforestartedit',
61070
61071             
61072             'startedit',
61073
61074             
61075             'beforecomplete',
61076             
61077             'complete',
61078             
61079             'canceledit',
61080             
61081             'specialkey'
61082         );
61083     },
61084
61085     
61086     onAutoSize: function(){
61087         this.doComponentLayout();
61088     },
61089
61090     
61091     onRender : function(ct, position) {
61092         var me = this,
61093             field = me.field,
61094             inputEl = field.inputEl;
61095
61096         me.callParent(arguments);
61097
61098         field.render(me.el);
61099         
61100         
61101         if (inputEl) {
61102             inputEl.dom.name = '';
61103             if (me.swallowKeys) {
61104                 inputEl.swallowEvent([
61105                     'keypress', 
61106                     'keydown'   
61107                 ]);
61108             }
61109         }
61110     },
61111
61112     
61113     onSpecialKey : function(field, event) {
61114         var me = this,
61115             key = event.getKey(),
61116             complete = me.completeOnEnter && key == event.ENTER,
61117             cancel = me.cancelOnEsc && key == event.ESC;
61118
61119         if (complete || cancel) {
61120             event.stopEvent();
61121             
61122             
61123             Ext.defer(function() {
61124                 if (complete) {
61125                     me.completeEdit();
61126                 } else {
61127                     me.cancelEdit();
61128                 }
61129                 if (field.triggerBlur) {
61130                     field.triggerBlur();
61131                 }
61132             }, 10);
61133         }
61134
61135         this.fireEvent('specialkey', this, field, event);
61136     },
61137
61138     
61139     startEdit : function(el, value) {
61140         var me = this,
61141             field = me.field;
61142
61143         me.completeEdit();
61144         me.boundEl = Ext.get(el);
61145         value = Ext.isDefined(value) ? value : me.boundEl.dom.innerHTML;
61146
61147         if (!me.rendered) {
61148             me.render(me.parentEl || document.body);
61149         }
61150
61151         if (me.fireEvent('beforestartedit', me, me.boundEl, value) !== false) {
61152             me.startValue = value;
61153             me.show();
61154             field.reset();
61155             field.setValue(value);
61156             me.realign(true);
61157             field.focus(false, 10);
61158             if (field.autoSize) {
61159                 field.autoSize();
61160             }
61161             me.editing = true;
61162         }
61163     },
61164
61165     
61166     realign : function(autoSize) {
61167         var me = this;
61168         if (autoSize === true) {
61169             me.doComponentLayout();
61170         }
61171         me.alignTo(me.boundEl, me.alignment, me.offsets);
61172     },
61173
61174     
61175     completeEdit : function(remainVisible) {
61176         var me = this,
61177             field = me.field,
61178             value;
61179
61180         if (!me.editing) {
61181             return;
61182         }
61183
61184         
61185         if (field.assertValue) {
61186             field.assertValue();
61187         }
61188
61189         value = me.getValue();
61190         if (!field.isValid()) {
61191             if (me.revertInvalid !== false) {
61192                 me.cancelEdit(remainVisible);
61193             }
61194             return;
61195         }
61196
61197         if (String(value) === String(me.startValue) && me.ignoreNoChange) {
61198             me.hideEdit(remainVisible);
61199             return;
61200         }
61201
61202         if (me.fireEvent('beforecomplete', me, value, me.startValue) !== false) {
61203             
61204             value = me.getValue();
61205             if (me.updateEl && me.boundEl) {
61206                 me.boundEl.update(value);
61207             }
61208             me.hideEdit(remainVisible);
61209             me.fireEvent('complete', me, value, me.startValue);
61210         }
61211     },
61212
61213     
61214     onShow : function() {
61215         var me = this;
61216
61217         me.callParent(arguments);
61218         if (me.hideEl !== false) {
61219             me.boundEl.hide();
61220         }
61221         me.fireEvent("startedit", me.boundEl, me.startValue);
61222     },
61223
61224     
61225     cancelEdit : function(remainVisible) {
61226         var me = this,
61227             startValue = me.startValue,
61228             value;
61229
61230         if (me.editing) {
61231             value = me.getValue();
61232             me.setValue(startValue);
61233             me.hideEdit(remainVisible);
61234             me.fireEvent('canceledit', me, value, startValue);
61235         }
61236     },
61237
61238     
61239     hideEdit: function(remainVisible) {
61240         if (remainVisible !== true) {
61241             this.editing = false;
61242             this.hide();
61243         }
61244     },
61245
61246     
61247     onBlur : function() {
61248         var me = this;
61249
61250         
61251         if(me.allowBlur === true && me.editing && me.selectSameEditor !== true) {
61252             me.completeEdit();
61253         }
61254     },
61255
61256     
61257     onHide : function() {
61258         var me = this,
61259             field = me.field;
61260
61261         if (me.editing) {
61262             me.completeEdit();
61263             return;
61264         }
61265         field.blur();
61266         if (field.collapse) {
61267             field.collapse();
61268         }
61269
61270         
61271         if (me.hideEl !== false) {
61272             me.boundEl.show();
61273         }
61274         me.callParent(arguments);
61275     },
61276
61277     
61278     setValue : function(value) {
61279         this.field.setValue(value);
61280     },
61281
61282     
61283     getValue : function() {
61284         return this.field.getValue();
61285     },
61286
61287     beforeDestroy : function() {
61288         var me = this;
61289
61290         Ext.destroy(me.field);
61291         delete me.field;
61292         delete me.parentEl;
61293         delete me.boundEl;
61294
61295         me.callParent(arguments);
61296     }
61297 });
61298
61299 Ext.define('Ext.Img', {
61300     extend: 'Ext.Component',
61301     alias: ['widget.image', 'widget.imagecomponent'],
61302     
61303     src: '',
61304
61305     getElConfig: function() {
61306         return {
61307             tag: 'img',
61308             src: this.src
61309         };
61310     },
61311     
61312     
61313     initRenderTpl: Ext.emptyFn,
61314     
61315     
61316     setSrc: function(src) {
61317         var me = this,
61318             img = me.el;
61319         me.src = src;
61320         if (img) {
61321             img.dom.src = src;
61322         }
61323     }
61324 });
61325
61326
61327 Ext.define('Ext.Layer', {
61328     uses: ['Ext.Shadow'],
61329
61330     
61331     statics: {
61332         shims: []
61333     },
61334
61335     extend: 'Ext.Element',
61336
61337     
61338     constructor: function(config, existingEl) {
61339         config = config || {};
61340         var me = this,
61341             dh = Ext.DomHelper,
61342             cp = config.parentEl,
61343             pel = cp ? Ext.getDom(cp) : document.body,
61344         hm = config.hideMode;
61345
61346         if (existingEl) {
61347             me.dom = Ext.getDom(existingEl);
61348         }
61349         if (!me.dom) {
61350             me.dom = dh.append(pel, config.dh || {
61351                 tag: 'div',
61352                 cls: Ext.baseCSSPrefix + 'layer'
61353             });
61354         } else {
61355             me.addCls(Ext.baseCSSPrefix + 'layer');
61356             if (!me.dom.parentNode) {
61357                 pel.appendChild(me.dom);
61358             }
61359         }
61360
61361         if (config.cls) {
61362             me.addCls(config.cls);
61363         }
61364         me.constrain = config.constrain !== false;
61365
61366         
61367         
61368         
61369         if (hm) {
61370             me.setVisibilityMode(Ext.Element[hm.toUpperCase()]);
61371             if (me.visibilityMode == Ext.Element.ASCLASS) {
61372                 me.visibilityCls = config.visibilityCls;
61373             }
61374         } else if (config.useDisplay) {
61375             me.setVisibilityMode(Ext.Element.DISPLAY);
61376         } else {
61377             me.setVisibilityMode(Ext.Element.VISIBILITY);
61378         }
61379
61380         if (config.id) {
61381             me.id = me.dom.id = config.id;
61382         } else {
61383             me.id = Ext.id(me.dom);
61384         }
61385         me.position('absolute');
61386         if (config.shadow) {
61387             me.shadowOffset = config.shadowOffset || 4;
61388             me.shadow = Ext.create('Ext.Shadow', {
61389                 offset: me.shadowOffset,
61390                 mode: config.shadow
61391             });
61392             me.disableShadow();
61393         } else {
61394             me.shadowOffset = 0;
61395         }
61396         me.useShim = config.shim !== false && Ext.useShims;
61397         if (config.hidden === true) {
61398             me.hide();
61399         } else {
61400             me.show();
61401         }
61402     },
61403
61404     getZIndex: function() {
61405         return parseInt((this.getShim() || this).getStyle('z-index'), 10);
61406     },
61407
61408     getShim: function() {
61409         var me = this,
61410             shim, pn;
61411
61412         if (!me.useShim) {
61413             return null;
61414         }
61415         if (!me.shim) {
61416             shim = me.self.shims.shift();
61417             if (!shim) {
61418                 shim = me.createShim();
61419                 shim.enableDisplayMode('block');
61420                 shim.hide();
61421             }
61422             pn = me.dom.parentNode;
61423             if (shim.dom.parentNode != pn) {
61424                 pn.insertBefore(shim.dom, me.dom);
61425             }
61426             me.shim = shim;
61427         }
61428         return me.shim;
61429     },
61430
61431     hideShim: function() {
61432         var me = this;
61433         
61434         if (me.shim) {
61435             me.shim.setDisplayed(false);
61436             me.self.shims.push(me.shim);
61437             delete me.shim;
61438         }
61439     },
61440
61441     disableShadow: function() {
61442         var me = this;
61443         
61444         if (me.shadow && !me.shadowDisabled) {
61445             me.shadowDisabled = true;
61446             me.shadow.hide();
61447             me.lastShadowOffset = me.shadowOffset;
61448             me.shadowOffset = 0;
61449         }
61450     },
61451
61452     enableShadow: function(show) {
61453         var me = this;
61454         
61455         if (me.shadow && me.shadowDisabled) {
61456             me.shadowDisabled = false;
61457             me.shadowOffset = me.lastShadowOffset;
61458             delete me.lastShadowOffset;
61459             if (show) {
61460                 me.sync(true);
61461             }
61462         }
61463     },
61464
61465     
61466     sync: function(doShow) {
61467         var me = this,
61468             shadow = me.shadow,
61469             shadowPos, shimStyle, shadowSize;
61470
61471         if (!me.updating && me.isVisible() && (shadow || me.useShim)) {
61472             var shim = me.getShim(),
61473                 l = me.getLeft(true),
61474                 t = me.getTop(true),
61475                 w = me.dom.offsetWidth,
61476                 h = me.dom.offsetHeight,
61477                 shimIndex;
61478
61479             if (shadow && !me.shadowDisabled) {
61480                 if (doShow && !shadow.isVisible()) {
61481                     shadow.show(me);
61482                 } else {
61483                     shadow.realign(l, t, w, h);
61484                 }
61485                 if (shim) {
61486                     
61487                     shimIndex = shim.getStyle('z-index');
61488                     if (shimIndex > me.zindex) {
61489                         me.shim.setStyle('z-index', me.zindex - 2);
61490                     }
61491                     shim.show();
61492                     
61493                     if (shadow.isVisible()) {
61494                         shadowPos = shadow.el.getXY();
61495                         shimStyle = shim.dom.style;
61496                         shadowSize = shadow.el.getSize();
61497                         if (Ext.supports.CSS3BoxShadow) {
61498                             shadowSize.height += 6;
61499                             shadowSize.width += 4;
61500                             shadowPos[0] -= 2;
61501                             shadowPos[1] -= 4;
61502                         }
61503                         shimStyle.left = (shadowPos[0]) + 'px';
61504                         shimStyle.top = (shadowPos[1]) + 'px';
61505                         shimStyle.width = (shadowSize.width) + 'px';
61506                         shimStyle.height = (shadowSize.height) + 'px';
61507                     } else {
61508                         shim.setSize(w, h);
61509                         shim.setLeftTop(l, t);
61510                     }
61511                 }
61512             } else if (shim) {
61513                 
61514                 shimIndex = shim.getStyle('z-index');
61515                 if (shimIndex > me.zindex) {
61516                     me.shim.setStyle('z-index', me.zindex - 2);
61517                 }
61518                 shim.show();
61519                 shim.setSize(w, h);
61520                 shim.setLeftTop(l, t);
61521             }
61522         }
61523         return me;
61524     },
61525
61526     remove: function() {
61527         this.hideUnders();
61528         this.callParent();
61529     },
61530
61531     
61532     beginUpdate: function() {
61533         this.updating = true;
61534     },
61535
61536     
61537     endUpdate: function() {
61538         this.updating = false;
61539         this.sync(true);
61540     },
61541
61542     
61543     hideUnders: function() {
61544         if (this.shadow) {
61545             this.shadow.hide();
61546         }
61547         this.hideShim();
61548     },
61549
61550     
61551     constrainXY: function() {
61552         if (this.constrain) {
61553             var vw = Ext.Element.getViewWidth(),
61554                 vh = Ext.Element.getViewHeight(),
61555                 s = Ext.getDoc().getScroll(),
61556                 xy = this.getXY(),
61557                 x = xy[0],
61558                 y = xy[1],
61559                 so = this.shadowOffset,
61560                 w = this.dom.offsetWidth + so,
61561                 h = this.dom.offsetHeight + so,
61562                 moved = false; 
61563             
61564             if ((x + w) > vw + s.left) {
61565                 x = vw - w - so;
61566                 moved = true;
61567             }
61568             if ((y + h) > vh + s.top) {
61569                 y = vh - h - so;
61570                 moved = true;
61571             }
61572             
61573             if (x < s.left) {
61574                 x = s.left;
61575                 moved = true;
61576             }
61577             if (y < s.top) {
61578                 y = s.top;
61579                 moved = true;
61580             }
61581             if (moved) {
61582                 Ext.Layer.superclass.setXY.call(this, [x, y]);
61583                 this.sync();
61584             }
61585         }
61586         return this;
61587     },
61588
61589     getConstrainOffset: function() {
61590         return this.shadowOffset;
61591     },
61592
61593     
61594     setVisible: function(visible, animate, duration, callback, easing) {
61595         var me = this,
61596             cb;
61597
61598         
61599         cb = function() {
61600             if (visible) {
61601                 me.sync(true);
61602             }
61603             if (callback) {
61604                 callback();
61605             }
61606         };
61607
61608         
61609         if (!visible) {
61610             me.hideUnders(true);
61611         }
61612         me.callParent([visible, animate, duration, callback, easing]);
61613         if (!animate) {
61614             cb();
61615         }
61616         return me;
61617     },
61618
61619     
61620     beforeFx: function() {
61621         this.beforeAction();
61622         return this.callParent(arguments);
61623     },
61624
61625     
61626     afterFx: function() {
61627         this.callParent(arguments);
61628         this.sync(this.isVisible());
61629     },
61630
61631     
61632     beforeAction: function() {
61633         if (!this.updating && this.shadow) {
61634             this.shadow.hide();
61635         }
61636     },
61637
61638     
61639     setLeft: function(left) {
61640         this.callParent(arguments);
61641         return this.sync();
61642     },
61643
61644     setTop: function(top) {
61645         this.callParent(arguments);
61646         return this.sync();
61647     },
61648
61649     setLeftTop: function(left, top) {
61650         this.callParent(arguments);
61651         return this.sync();
61652     },
61653
61654     setXY: function(xy, animate, duration, callback, easing) {
61655         var me = this;
61656         
61657         
61658         callback = me.createCB(callback);
61659
61660         me.fixDisplay();
61661         me.beforeAction();
61662         me.callParent([xy, animate, duration, callback, easing]);
61663         if (!animate) {
61664             callback();
61665         }
61666         return me;
61667     },
61668
61669     
61670     createCB: function(callback) {
61671         var me = this,
61672             showShadow = me.shadow && me.shadow.isVisible();
61673
61674         return function() {
61675             me.constrainXY();
61676             me.sync(showShadow);
61677             if (callback) {
61678                 callback();
61679             }
61680         };
61681     },
61682
61683     
61684     setX: function(x, animate, duration, callback, easing) {
61685         this.setXY([x, this.getY()], animate, duration, callback, easing);
61686         return this;
61687     },
61688
61689     
61690     setY: function(y, animate, duration, callback, easing) {
61691         this.setXY([this.getX(), y], animate, duration, callback, easing);
61692         return this;
61693     },
61694
61695     
61696     setSize: function(w, h, animate, duration, callback, easing) {
61697         var me = this;
61698         
61699         
61700         callback = me.createCB(callback);
61701
61702         me.beforeAction();
61703         me.callParent([w, h, animate, duration, callback, easing]);
61704         if (!animate) {
61705             callback();
61706         }
61707         return me;
61708     },
61709
61710     
61711     setWidth: function(w, animate, duration, callback, easing) {
61712         var me = this;
61713         
61714         
61715         callback = me.createCB(callback);
61716
61717         me.beforeAction();
61718         me.callParent([w, animate, duration, callback, easing]);
61719         if (!animate) {
61720             callback();
61721         }
61722         return me;
61723     },
61724
61725     
61726     setHeight: function(h, animate, duration, callback, easing) {
61727         var me = this;
61728         
61729         
61730         callback = me.createCB(callback);
61731
61732         me.beforeAction();
61733         me.callParent([h, animate, duration, callback, easing]);
61734         if (!animate) {
61735             callback();
61736         }
61737         return me;
61738     },
61739
61740     
61741     setBounds: function(x, y, width, height, animate, duration, callback, easing) {
61742         var me = this;
61743         
61744         
61745         callback = me.createCB(callback);
61746
61747         me.beforeAction();
61748         if (!animate) {
61749             Ext.Layer.superclass.setXY.call(me, [x, y]);
61750             Ext.Layer.superclass.setSize.call(me, width, height);
61751             callback();
61752         } else {
61753             me.callParent([x, y, width, height, animate, duration, callback, easing]);
61754         }
61755         return me;
61756     },
61757
61758     
61759     setZIndex: function(zindex) {
61760         var me = this;
61761         
61762         me.zindex = zindex;
61763         if (me.getShim()) {
61764             me.shim.setStyle('z-index', zindex++);
61765         }
61766         if (me.shadow) {
61767             me.shadow.setZIndex(zindex++);
61768         }
61769         return me.setStyle('z-index', zindex);
61770     },
61771     
61772     setOpacity: function(opacity){
61773         if (this.shadow) {
61774             this.shadow.setOpacity(opacity);
61775         }
61776         return this.callParent(arguments);
61777     }
61778 });
61779
61780
61781
61782 Ext.define('Ext.layout.component.ProgressBar', {
61783
61784     
61785
61786     alias: ['layout.progressbar'],
61787
61788     extend: 'Ext.layout.component.Component',
61789
61790     
61791
61792     type: 'progressbar',
61793
61794     onLayout: function(width, height) {
61795         var me = this,
61796             owner = me.owner,
61797             textEl = owner.textEl;
61798         
61799         me.setElementSize(owner.el, width, height);
61800         textEl.setWidth(owner.el.getWidth(true));
61801         
61802         me.callParent([width, height]);
61803         
61804         owner.updateProgress(owner.value);
61805     }
61806 });
61807
61808 Ext.define('Ext.ProgressBar', {
61809     extend: 'Ext.Component',
61810     alias: 'widget.progressbar',
61811
61812     requires: [
61813         'Ext.Template',
61814         'Ext.CompositeElement',
61815         'Ext.TaskManager',
61816         'Ext.layout.component.ProgressBar'
61817     ],
61818
61819     uses: ['Ext.fx.Anim'],
61820
61821    
61822
61823    
61824
61825    
61826
61827    
61828
61829    
61830     baseCls: Ext.baseCSSPrefix + 'progress',
61831
61832     config: {
61833         
61834         animate: false,
61835
61836         
61837         text: ''
61838     },
61839
61840     
61841     waitTimer: null,
61842
61843     renderTpl: [
61844         '<div class="{baseCls}-text {baseCls}-text-back">',
61845             '<div>&#160;</div>',
61846         '</div>',
61847         '<div id="{id}-bar" class="{baseCls}-bar">',
61848             '<div class="{baseCls}-text">',
61849                 '<div>&#160;</div>',
61850             '</div>',
61851         '</div>'
61852     ],
61853
61854     componentLayout: 'progressbar',
61855
61856     
61857     initComponent: function() {
61858         this.callParent();
61859
61860         this.addChildEls('bar');
61861
61862         this.addEvents(
61863             
61864             "update"
61865         );
61866     },
61867
61868     afterRender : function() {
61869         var me = this;
61870
61871         
61872         
61873         me.textEl = me.textEl ? Ext.get(me.textEl) : me.el.select('.' + me.baseCls + '-text');
61874
61875         me.callParent(arguments);
61876
61877         if (me.value) {
61878             me.updateProgress(me.value, me.text);
61879         }
61880         else {
61881             me.updateText(me.text);
61882         }
61883     },
61884
61885     
61886     updateProgress: function(value, text, animate) {
61887         var me = this,
61888             newWidth;
61889             
61890         me.value = value || 0;
61891         if (text) {
61892             me.updateText(text);
61893         }
61894         if (me.rendered && !me.isDestroyed) {
61895             if (me.isVisible(true)) {
61896                 newWidth = Math.floor(me.value * me.el.getWidth(true));
61897                 if (Ext.isForcedBorderBox) {
61898                     newWidth += me.bar.getBorderWidth("lr");
61899                 }
61900                 if (animate === true || (animate !== false && me.animate)) {
61901                     me.bar.stopAnimation();
61902                     me.bar.animate(Ext.apply({
61903                         to: {
61904                             width: newWidth + 'px'
61905                         }
61906                     }, me.animate));
61907                 } else {
61908                     me.bar.setWidth(newWidth);
61909                 }
61910             } else {
61911                 
61912                 me.doComponentLayout();
61913             }
61914         }
61915         me.fireEvent('update', me, me.value, text);
61916         return me;
61917     },
61918
61919     
61920     updateText: function(text) {
61921         var me = this;
61922         
61923         me.text = text;
61924         if (me.rendered) {
61925             me.textEl.update(me.text);
61926         }
61927         return me;
61928     },
61929
61930     applyText : function(text) {
61931         this.updateText(text);
61932     },
61933
61934     
61935     wait: function(o) {
61936         var me = this;
61937             
61938         if (!me.waitTimer) {
61939             scope = me;
61940             o = o || {};
61941             me.updateText(o.text);
61942             me.waitTimer = Ext.TaskManager.start({
61943                 run: function(i){
61944                     var inc = o.increment || 10;
61945                     i -= 1;
61946                     me.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
61947                 },
61948                 interval: o.interval || 1000,
61949                 duration: o.duration,
61950                 onStop: function(){
61951                     if (o.fn) {
61952                         o.fn.apply(o.scope || me);
61953                     }
61954                     me.reset();
61955                 },
61956                 scope: scope
61957             });
61958         }
61959         return me;
61960     },
61961
61962     
61963     isWaiting: function(){
61964         return this.waitTimer !== null;
61965     },
61966
61967     
61968     reset: function(hide){
61969         var me = this;
61970         
61971         me.updateProgress(0);
61972         me.clearTimer();
61973         if (hide === true) {
61974             me.hide();
61975         }
61976         return me;
61977     },
61978
61979     
61980     clearTimer: function(){
61981         var me = this;
61982         
61983         if (me.waitTimer) {
61984             me.waitTimer.onStop = null; 
61985             Ext.TaskManager.stop(me.waitTimer);
61986             me.waitTimer = null;
61987         }
61988     },
61989
61990     onDestroy: function(){
61991         var me = this;
61992         
61993         me.clearTimer();
61994         if (me.rendered) {
61995             if (me.textEl.isComposite) {
61996                 me.textEl.clear();
61997             }
61998             Ext.destroyMembers(me, 'textEl', 'progressBar');
61999         }
62000         me.callParent();
62001     }
62002 });
62003
62004
62005 Ext.define('Ext.ShadowPool', {
62006     singleton: true,
62007     requires: ['Ext.DomHelper'],
62008
62009     markup: function() {
62010         if (Ext.supports.CSS3BoxShadow) {
62011             return '<div class="' + Ext.baseCSSPrefix + 'css-shadow" role="presentation"></div>';
62012         } else if (Ext.isIE) {
62013             return '<div class="' + Ext.baseCSSPrefix + 'ie-shadow" role="presentation"></div>';
62014         } else {
62015             return '<div class="' + Ext.baseCSSPrefix + 'frame-shadow" role="presentation">' +
62016                 '<div class="xst" role="presentation">' +
62017                     '<div class="xstl" role="presentation"></div>' +
62018                     '<div class="xstc" role="presentation"></div>' +
62019                     '<div class="xstr" role="presentation"></div>' +
62020                 '</div>' +
62021                 '<div class="xsc" role="presentation">' +
62022                     '<div class="xsml" role="presentation"></div>' +
62023                     '<div class="xsmc" role="presentation"></div>' +
62024                     '<div class="xsmr" role="presentation"></div>' +
62025                 '</div>' +
62026                 '<div class="xsb" role="presentation">' +
62027                     '<div class="xsbl" role="presentation"></div>' +
62028                     '<div class="xsbc" role="presentation"></div>' +
62029                     '<div class="xsbr" role="presentation"></div>' +
62030                 '</div>' +
62031             '</div>';
62032         }
62033     }(),
62034
62035     shadows: [],
62036
62037     pull: function() {
62038         var sh = this.shadows.shift();
62039         if (!sh) {
62040             sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, this.markup));
62041             sh.autoBoxAdjust = false;
62042         }
62043         return sh;
62044     },
62045
62046     push: function(sh) {
62047         this.shadows.push(sh);
62048     },
62049     
62050     reset: function() {
62051         Ext.Array.each(this.shadows, function(shadow) {
62052             shadow.remove();
62053         });
62054         this.shadows = [];
62055     }
62056 });
62057
62058 Ext.define('Ext.Shadow', {
62059     requires: ['Ext.ShadowPool'],
62060
62061     
62062     constructor: function(config) {
62063         var me = this,
62064             adjusts = {
62065                 h: 0
62066             },
62067             offset,
62068             rad;
62069         
62070         Ext.apply(me, config);
62071         if (!Ext.isString(me.mode)) {
62072             me.mode = me.defaultMode;
62073         }
62074         offset = me.offset;
62075         rad = Math.floor(offset / 2);
62076         me.opacity = 50;
62077         switch (me.mode.toLowerCase()) {
62078             
62079             case "drop":
62080                 if (Ext.supports.CSS3BoxShadow) {
62081                     adjusts.w = adjusts.h = -offset;
62082                     adjusts.l = adjusts.t = offset;
62083                 } else {
62084                     adjusts.w = 0;
62085                     adjusts.l = adjusts.t = offset;
62086                     adjusts.t -= 1;
62087                     if (Ext.isIE) {
62088                         adjusts.l -= offset + rad;
62089                         adjusts.t -= offset + rad;
62090                         adjusts.w -= rad;
62091                         adjusts.h -= rad;
62092                         adjusts.t += 1;
62093                     }
62094                 }
62095                 break;
62096             case "sides":
62097                 if (Ext.supports.CSS3BoxShadow) {
62098                     adjusts.h -= offset;
62099                     adjusts.t = offset;
62100                     adjusts.l = adjusts.w = 0;
62101                 } else {
62102                     adjusts.w = (offset * 2);
62103                     adjusts.l = -offset;
62104                     adjusts.t = offset - 1;
62105                     if (Ext.isIE) {
62106                         adjusts.l -= (offset - rad);
62107                         adjusts.t -= offset + rad;
62108                         adjusts.l += 1;
62109                         adjusts.w -= (offset - rad) * 2;
62110                         adjusts.w -= rad + 1;
62111                         adjusts.h -= 1;
62112                     }
62113                 }
62114                 break;
62115             case "frame":
62116                 if (Ext.supports.CSS3BoxShadow) {
62117                     adjusts.l = adjusts.w = adjusts.t = 0;
62118                 } else {
62119                     adjusts.w = adjusts.h = (offset * 2);
62120                     adjusts.l = adjusts.t = -offset;
62121                     adjusts.t += 1;
62122                     adjusts.h -= 2;
62123                     if (Ext.isIE) {
62124                         adjusts.l -= (offset - rad);
62125                         adjusts.t -= (offset - rad);
62126                         adjusts.l += 1;
62127                         adjusts.w -= (offset + rad + 1);
62128                         adjusts.h -= (offset + rad);
62129                         adjusts.h += 1;
62130                     }
62131                     break;
62132                 }
62133         }
62134         me.adjusts = adjusts;
62135     },
62136
62137     
62138     
62139     offset: 4,
62140
62141     
62142     defaultMode: "drop",
62143
62144     
62145     show: function(target) {
62146         var me = this,
62147             index;
62148         
62149         target = Ext.get(target);
62150         if (!me.el) {
62151             me.el = Ext.ShadowPool.pull();
62152             if (me.el.dom.nextSibling != target.dom) {
62153                 me.el.insertBefore(target);
62154             }
62155         }
62156         index = (parseInt(target.getStyle("z-index"), 10) - 1) || 0;
62157         me.el.setStyle("z-index", me.zIndex || index);
62158         if (Ext.isIE && !Ext.supports.CSS3BoxShadow) {
62159             me.el.dom.style.filter = "progid:DXImageTransform.Microsoft.alpha(opacity=" + me.opacity + ") progid:DXImageTransform.Microsoft.Blur(pixelradius=" + (me.offset) + ")";
62160         }
62161         me.realign(
62162             target.getLeft(true),
62163             target.getTop(true),
62164             target.dom.offsetWidth,
62165             target.dom.offsetHeight
62166         );
62167         me.el.dom.style.display = "block";
62168     },
62169
62170     
62171     isVisible: function() {
62172         return this.el ? true: false;
62173     },
62174
62175     
62176     realign: function(l, t, targetWidth, targetHeight) {
62177         if (!this.el) {
62178             return;
62179         }
62180         var adjusts = this.adjusts,
62181             d = this.el.dom,
62182             targetStyle = d.style,
62183             shadowWidth,
62184             shadowHeight,
62185             cn,
62186             sww, 
62187             sws, 
62188             shs;
62189
62190         targetStyle.left = (l + adjusts.l) + "px";
62191         targetStyle.top = (t + adjusts.t) + "px";
62192         shadowWidth = Math.max(targetWidth + adjusts.w, 0);
62193         shadowHeight = Math.max(targetHeight + adjusts.h, 0);
62194         sws = shadowWidth + "px";
62195         shs = shadowHeight + "px";
62196         if (targetStyle.width != sws || targetStyle.height != shs) {
62197             targetStyle.width = sws;
62198             targetStyle.height = shs;
62199             if (Ext.supports.CSS3BoxShadow) {
62200                 targetStyle.boxShadow = '0 0 ' + this.offset + 'px 0 #888';
62201             } else {
62202
62203                 
62204                 if (!Ext.isIE) {
62205                     cn = d.childNodes;
62206                     sww = Math.max(0, (shadowWidth - 12)) + "px";
62207                     cn[0].childNodes[1].style.width = sww;
62208                     cn[1].childNodes[1].style.width = sww;
62209                     cn[2].childNodes[1].style.width = sww;
62210                     cn[1].style.height = Math.max(0, (shadowHeight - 12)) + "px";
62211                 }
62212             }
62213         }
62214     },
62215
62216     
62217     hide: function() {
62218         var me = this;
62219         
62220         if (me.el) {
62221             me.el.dom.style.display = "none";
62222             Ext.ShadowPool.push(me.el);
62223             delete me.el;
62224         }
62225     },
62226
62227     
62228     setZIndex: function(z) {
62229         this.zIndex = z;
62230         if (this.el) {
62231             this.el.setStyle("z-index", z);
62232         }
62233     },
62234     
62235     
62236     setOpacity: function(opacity){
62237         if (this.el) {
62238             if (Ext.isIE && !Ext.supports.CSS3BoxShadow) {
62239                 opacity = Math.floor(opacity * 100 / 2) / 100;
62240             }
62241             this.opacity = opacity;
62242             this.el.setOpacity(opacity);
62243         }
62244     }
62245 });
62246
62247 Ext.define('Ext.button.Split', {
62248
62249     
62250     alias: 'widget.splitbutton',
62251
62252     extend: 'Ext.button.Button',
62253     alternateClassName: 'Ext.SplitButton',
62254     
62255     
62256     
62257     
62258
62259     
62260     arrowCls      : 'split',
62261     split         : true,
62262
62263     
62264     initComponent : function(){
62265         this.callParent();
62266         
62267         this.addEvents("arrowclick");
62268     },
62269
62270     
62271     setArrowHandler : function(handler, scope){
62272         this.arrowHandler = handler;
62273         this.scope = scope;
62274     },
62275
62276     
62277     onClick : function(e, t) {
62278         var me = this;
62279         
62280         e.preventDefault();
62281         if (!me.disabled) {
62282             if (me.overMenuTrigger) {
62283                 me.maybeShowMenu();
62284                 me.fireEvent("arrowclick", me, e);
62285                 if (me.arrowHandler) {
62286                     me.arrowHandler.call(me.scope || me, me, e);
62287                 }
62288             } else {
62289                 me.doToggle();
62290                 me.fireHandler();
62291             }
62292         }
62293     }
62294 });
62295
62296 Ext.define('Ext.button.Cycle', {
62297
62298     
62299
62300     alias: 'widget.cycle',
62301
62302     extend: 'Ext.button.Split',
62303     alternateClassName: 'Ext.CycleButton',
62304
62305     
62306
62307     
62308     
62309     
62310     
62311     
62312     
62313
62314     
62315     getButtonText: function(item) {
62316         var me = this,
62317             text = '';
62318
62319         if (item && me.showText === true) {
62320             if (me.prependText) {
62321                 text += me.prependText;
62322             }
62323             text += item.text;
62324             return text;
62325         }
62326         return me.text;
62327     },
62328
62329     
62330     setActiveItem: function(item, suppressEvent) {
62331         var me = this;
62332
62333         if (!Ext.isObject(item)) {
62334             item = me.menu.getComponent(item);
62335         }
62336         if (item) {
62337             if (!me.rendered) {
62338                 me.text = me.getButtonText(item);
62339                 me.iconCls = item.iconCls;
62340             } else {
62341                 me.setText(me.getButtonText(item));
62342                 me.setIconCls(item.iconCls);
62343             }
62344             me.activeItem = item;
62345             if (!item.checked) {
62346                 item.setChecked(true, false);
62347             }
62348             if (me.forceIcon) {
62349                 me.setIconCls(me.forceIcon);
62350             }
62351             if (!suppressEvent) {
62352                 me.fireEvent('change', me, item);
62353             }
62354         }
62355     },
62356
62357     
62358     getActiveItem: function() {
62359         return this.activeItem;
62360     },
62361
62362     
62363     initComponent: function() {
62364         var me = this,
62365             checked = 0,
62366             items;
62367
62368         me.addEvents(
62369             
62370             "change"
62371         );
62372
62373         if (me.changeHandler) {
62374             me.on('change', me.changeHandler, me.scope || me);
62375             delete me.changeHandler;
62376         }
62377
62378         
62379         
62380         items = (me.menu.items||[]).concat(me.items||[]);
62381         me.menu = Ext.applyIf({
62382             cls: Ext.baseCSSPrefix + 'cycle-menu',
62383             items: []
62384         }, me.menu);
62385
62386         
62387         Ext.each(items, function(item, i) {
62388             item = Ext.applyIf({
62389                 group: me.id,
62390                 itemIndex: i,
62391                 checkHandler: me.checkHandler,
62392                 scope: me,
62393                 checked: item.checked || false
62394             }, item);
62395             me.menu.items.push(item);
62396             if (item.checked) {
62397                 checked = i;
62398             }
62399         });
62400         me.itemCount = me.menu.items.length;
62401         me.callParent(arguments);
62402         me.on('click', me.toggleSelected, me);
62403         me.setActiveItem(checked, me);
62404
62405         
62406         if (me.width && me.showText) {
62407             me.addCls(Ext.baseCSSPrefix + 'cycle-fixed-width');
62408         }
62409     },
62410
62411     
62412     checkHandler: function(item, pressed) {
62413         if (pressed) {
62414             this.setActiveItem(item);
62415         }
62416     },
62417
62418     
62419     toggleSelected: function() {
62420         var me = this,
62421             m = me.menu,
62422             checkItem;
62423
62424         checkItem = me.activeItem.next(':not([disabled])') || m.items.getAt(0);
62425         checkItem.setChecked(true);
62426     }
62427 });
62428
62429 Ext.define('Ext.container.ButtonGroup', {
62430     extend: 'Ext.panel.Panel',
62431     alias: 'widget.buttongroup',
62432     alternateClassName: 'Ext.ButtonGroup',
62433
62434     
62435
62436     
62437     baseCls: Ext.baseCSSPrefix + 'btn-group',
62438
62439     
62440     layout: {
62441         type: 'table'
62442     },
62443
62444     defaultType: 'button',
62445
62446     
62447     frame: true,
62448
62449     frameHeader: false,
62450
62451     internalDefaults: {removeMode: 'container', hideParent: true},
62452
62453     initComponent : function(){
62454         
62455         var me = this,
62456             cols = me.columns;
62457
62458         me.noTitleCls = me.baseCls + '-notitle';
62459         if (cols) {
62460             me.layout = Ext.apply({}, {columns: cols}, me.layout);
62461         }
62462
62463         if (!me.title) {
62464             me.addCls(me.noTitleCls);
62465         }
62466         me.callParent(arguments);
62467     },
62468
62469     afterLayout: function() {
62470         var me = this;
62471
62472         me.callParent(arguments);
62473
62474         
62475         
62476         if (me.layout.table && (Ext.isIEQuirks || Ext.isIE6) && !me.width) {
62477             var t = me.getTargetEl();
62478             t.setWidth(me.layout.table.offsetWidth + t.getPadding('lr'));
62479         }
62480
62481         
62482         if (Ext.isIE7) {
62483             me.el.repaint();
62484         }
62485     },
62486
62487     afterRender: function() {
62488         var me = this;
62489
62490         
62491         if (me.header) {
62492             
62493             delete me.header.items.items[0].flex;
62494
62495             
62496             me.suspendLayout = true;
62497             me.header.insert(1, {
62498                 xtype: 'component',
62499                 ui   : me.ui,
62500                 flex : 1
62501             });
62502             me.header.insert(0, {
62503                 xtype: 'component',
62504                 ui   : me.ui,
62505                 flex : 1
62506             });
62507             me.suspendLayout = false;
62508         }
62509
62510         me.callParent(arguments);
62511     },
62512
62513     
62514     onBeforeAdd: function(component) {
62515         if (component.is('button')) {
62516             component.ui = component.ui + '-toolbar';
62517         }
62518         this.callParent(arguments);
62519     },
62520
62521     
62522     applyDefaults: function(c) {
62523         if (!Ext.isString(c)) {
62524             c = this.callParent(arguments);
62525             var d = this.internalDefaults;
62526             if (c.events) {
62527                 Ext.applyIf(c.initialConfig, d);
62528                 Ext.apply(c, d);
62529             } else {
62530                 Ext.applyIf(c, d);
62531             }
62532         }
62533         return c;
62534     }
62535
62536     
62537     
62538     
62539     
62540     
62541 });
62542
62543
62544 Ext.define('Ext.container.Viewport', {
62545     extend: 'Ext.container.Container',
62546     alias: 'widget.viewport',
62547     requires: ['Ext.EventManager'],
62548     alternateClassName: 'Ext.Viewport',
62549
62550     
62551     
62552     
62553
62554     
62555
62556     
62557
62558     
62559
62560     
62561
62562     
62563
62564     
62565
62566     
62567
62568     
62569
62570     
62571
62572     
62573
62574     
62575
62576     isViewport: true,
62577
62578     ariaRole: 'application',
62579
62580     initComponent : function() {
62581         var me = this,
62582             html = Ext.fly(document.body.parentNode),
62583             el;
62584         me.callParent(arguments);
62585         html.addCls(Ext.baseCSSPrefix + 'viewport');
62586         if (me.autoScroll) {
62587             html.setStyle('overflow', 'auto');
62588         }
62589         me.el = el = Ext.getBody();
62590         el.setHeight = Ext.emptyFn;
62591         el.setWidth = Ext.emptyFn;
62592         el.setSize = Ext.emptyFn;
62593         el.dom.scroll = 'no';
62594         me.allowDomMove = false;
62595         Ext.EventManager.onWindowResize(me.fireResize, me);
62596         me.renderTo = me.el;
62597         me.width = Ext.Element.getViewportWidth();
62598         me.height = Ext.Element.getViewportHeight();
62599     },
62600
62601     fireResize : function(w, h){
62602         
62603         this.setSize(w, h);
62604     }
62605 });
62606
62607
62608
62609
62610
62611 Ext.define('Ext.dd.DDTarget', {
62612     extend: 'Ext.dd.DragDrop',
62613
62614     
62615     constructor: function(id, sGroup, config) {
62616         if (id) {
62617             this.initTarget(id, sGroup, config);
62618         }
62619     },
62620
62621     
62622     getDragEl: Ext.emptyFn,
62623     
62624     isValidHandleChild: Ext.emptyFn,
62625     
62626     startDrag: Ext.emptyFn,
62627     
62628     endDrag: Ext.emptyFn,
62629     
62630     onDrag: Ext.emptyFn,
62631     
62632     onDragDrop: Ext.emptyFn,
62633     
62634     onDragEnter: Ext.emptyFn,
62635     
62636     onDragOut: Ext.emptyFn,
62637     
62638     onDragOver: Ext.emptyFn,
62639     
62640     onInvalidDrop: Ext.emptyFn,
62641     
62642     onMouseDown: Ext.emptyFn,
62643     
62644     onMouseUp: Ext.emptyFn,
62645     
62646     setXConstraint: Ext.emptyFn,
62647     
62648     setYConstraint: Ext.emptyFn,
62649     
62650     resetConstraints: Ext.emptyFn,
62651     
62652     clearConstraints: Ext.emptyFn,
62653     
62654     clearTicks: Ext.emptyFn,
62655     
62656     setInitPosition: Ext.emptyFn,
62657     
62658     setDragElId: Ext.emptyFn,
62659     
62660     setHandleElId: Ext.emptyFn,
62661     
62662     setOuterHandleElId: Ext.emptyFn,
62663     
62664     addInvalidHandleClass: Ext.emptyFn,
62665     
62666     addInvalidHandleId: Ext.emptyFn,
62667     
62668     addInvalidHandleType: Ext.emptyFn,
62669     
62670     removeInvalidHandleClass: Ext.emptyFn,
62671     
62672     removeInvalidHandleId: Ext.emptyFn,
62673     
62674     removeInvalidHandleType: Ext.emptyFn,
62675
62676     toString: function() {
62677         return ("DDTarget " + this.id);
62678     }
62679 });
62680
62681 Ext.define('Ext.dd.DragTracker', {
62682
62683     uses: ['Ext.util.Region'],
62684
62685     mixins: {
62686         observable: 'Ext.util.Observable'
62687     },
62688
62689     
62690     active: false,
62691
62692     
62693
62694     
62695     trackOver: false,
62696
62697     
62698
62699     
62700
62701     
62702     tolerance: 5,
62703
62704     
62705     autoStart: false,
62706
62707     
62708
62709     
62710
62711     
62712
62713     constructor : function(config){
62714         Ext.apply(this, config);
62715         this.addEvents(
62716             
62717             'mouseover',
62718
62719             
62720             'mouseout',
62721
62722             
62723             'mousedown',
62724
62725             
62726             'mouseup',
62727
62728             
62729             'mousemove',
62730
62731             
62732             'beforedragstart',
62733
62734             
62735             'dragstart',
62736
62737             
62738             'dragend',
62739
62740             
62741             'drag'
62742         );
62743
62744         this.dragRegion = Ext.create('Ext.util.Region', 0,0,0,0);
62745
62746         if (this.el) {
62747             this.initEl(this.el);
62748         }
62749
62750         
62751         this.mixins.observable.constructor.call(this);
62752         if (this.disabled) {
62753             this.disable();
62754         }
62755
62756     },
62757
62758     
62759     initEl: function(el) {
62760         this.el = Ext.get(el);
62761
62762         
62763         this.handle = Ext.get(this.delegate);
62764
62765         
62766         this.delegate = this.handle ? undefined : this.delegate;
62767
62768         if (!this.handle) {
62769             this.handle = this.el;
62770         }
62771
62772         
62773         
62774         this.mon(this.handle, {
62775             mousedown: this.onMouseDown,
62776             delegate: this.delegate,
62777             scope: this
62778         });
62779
62780         
62781         
62782         
62783         if (this.trackOver || this.overCls) {
62784             this.mon(this.handle, {
62785                 mouseover: this.onMouseOver,
62786                 mouseout: this.onMouseOut,
62787                 delegate: this.delegate,
62788                 scope: this
62789             });
62790         }
62791     },
62792
62793     disable: function() {
62794         this.disabled = true;
62795     },
62796
62797     enable: function() {
62798         this.disabled = false;
62799     },
62800
62801     destroy : function() {
62802         this.clearListeners();
62803         delete this.el;
62804     },
62805
62806     
62807     
62808     onMouseOver: function(e, target) {
62809         var me = this;
62810         if (!me.disabled) {
62811             if (Ext.EventManager.contains(e) || me.delegate) {
62812                 me.mouseIsOut = false;
62813                 if (me.overCls) {
62814                     me.el.addCls(me.overCls);
62815                 }
62816                 me.fireEvent('mouseover', me, e, me.delegate ? e.getTarget(me.delegate, target) : me.handle);
62817             }
62818         }
62819     },
62820
62821     
62822     
62823     onMouseOut: function(e) {
62824         if (this.mouseIsDown) {
62825             this.mouseIsOut = true;
62826         } else {
62827             if (this.overCls) {
62828                 this.el.removeCls(this.overCls);
62829             }
62830             this.fireEvent('mouseout', this, e);
62831         }
62832     },
62833
62834     onMouseDown: function(e, target){
62835         
62836         if (this.disabled ||e.dragTracked) {
62837             return;
62838         }
62839
62840         
62841         this.dragTarget = this.delegate ? target : this.handle.dom;
62842         this.startXY = this.lastXY = e.getXY();
62843         this.startRegion = Ext.fly(this.dragTarget).getRegion();
62844
62845         if (this.fireEvent('mousedown', this, e) === false ||
62846             this.fireEvent('beforedragstart', this, e) === false ||
62847             this.onBeforeStart(e) === false) {
62848             return;
62849         }
62850
62851         
62852         
62853         this.mouseIsDown = true;
62854
62855         
62856         e.dragTracked = true;
62857
62858         if (this.preventDefault !== false) {
62859             e.preventDefault();
62860         }
62861         Ext.getDoc().on({
62862             scope: this,
62863             mouseup: this.onMouseUp,
62864             mousemove: this.onMouseMove,
62865             selectstart: this.stopSelect
62866         });
62867         if (this.autoStart) {
62868             this.timer =  Ext.defer(this.triggerStart, this.autoStart === true ? 1000 : this.autoStart, this, [e]);
62869         }
62870     },
62871
62872     onMouseMove: function(e, target){
62873         
62874         
62875         if (this.active && Ext.isIE && !e.browserEvent.button) {
62876             e.preventDefault();
62877             this.onMouseUp(e);
62878             return;
62879         }
62880
62881         e.preventDefault();
62882         var xy = e.getXY(),
62883             s = this.startXY;
62884
62885         this.lastXY = xy;
62886         if (!this.active) {
62887             if (Math.max(Math.abs(s[0]-xy[0]), Math.abs(s[1]-xy[1])) > this.tolerance) {
62888                 this.triggerStart(e);
62889             } else {
62890                 return;
62891             }
62892         }
62893
62894         
62895         if (this.fireEvent('mousemove', this, e) === false) {
62896             this.onMouseUp(e);
62897         } else {
62898             this.onDrag(e);
62899             this.fireEvent('drag', this, e);
62900         }
62901     },
62902
62903     onMouseUp: function(e) {
62904         
62905         
62906         this.mouseIsDown = false;
62907
62908         
62909         if (this.mouseIsOut) {
62910             this.mouseIsOut = false;
62911             this.onMouseOut(e);
62912         }
62913         e.preventDefault();
62914         this.fireEvent('mouseup', this, e);
62915         this.endDrag(e);
62916     },
62917
62918     
62919     endDrag: function(e) {
62920         var doc = Ext.getDoc(),
62921         wasActive = this.active;
62922
62923         doc.un('mousemove', this.onMouseMove, this);
62924         doc.un('mouseup', this.onMouseUp, this);
62925         doc.un('selectstart', this.stopSelect, this);
62926         this.clearStart();
62927         this.active = false;
62928         if (wasActive) {
62929             this.onEnd(e);
62930             this.fireEvent('dragend', this, e);
62931         }
62932         
62933         delete this._constrainRegion;
62934
62935         
62936         delete Ext.EventObject.dragTracked;
62937     },
62938
62939     triggerStart: function(e) {
62940         this.clearStart();
62941         this.active = true;
62942         this.onStart(e);
62943         this.fireEvent('dragstart', this, e);
62944     },
62945
62946     clearStart : function() {
62947         if (this.timer) {
62948             clearTimeout(this.timer);
62949             delete this.timer;
62950         }
62951     },
62952
62953     stopSelect : function(e) {
62954         e.stopEvent();
62955         return false;
62956     },
62957
62958     
62959     onBeforeStart : function(e) {
62960
62961     },
62962
62963     
62964     onStart : function(xy) {
62965
62966     },
62967
62968     
62969     onDrag : function(e) {
62970
62971     },
62972
62973     
62974     onEnd : function(e) {
62975
62976     },
62977
62978     
62979     getDragTarget : function(){
62980         return this.dragTarget;
62981     },
62982
62983     
62984     getDragCt : function(){
62985         return this.el;
62986     },
62987
62988     
62989     getConstrainRegion: function() {
62990         if (this.constrainTo) {
62991             if (this.constrainTo instanceof Ext.util.Region) {
62992                 return this.constrainTo;
62993             }
62994             if (!this._constrainRegion) {
62995                 this._constrainRegion = Ext.fly(this.constrainTo).getViewRegion();
62996             }
62997         } else {
62998             if (!this._constrainRegion) {
62999                 this._constrainRegion = this.getDragCt().getViewRegion();
63000             }
63001         }
63002         return this._constrainRegion;
63003     },
63004
63005     getXY : function(constrain){
63006         return constrain ? this.constrainModes[constrain](this, this.lastXY) : this.lastXY;
63007     },
63008
63009     
63010     getOffset : function(constrain){
63011         var xy = this.getXY(constrain),
63012             s = this.startXY;
63013
63014         return [xy[0]-s[0], xy[1]-s[1]];
63015     },
63016
63017     constrainModes: {
63018         
63019         point: function(me, xy) {
63020             var dr = me.dragRegion,
63021                 constrainTo = me.getConstrainRegion();
63022
63023             
63024             if (!constrainTo) {
63025                 return xy;
63026             }
63027
63028             dr.x = dr.left = dr[0] = dr.right = xy[0];
63029             dr.y = dr.top = dr[1] = dr.bottom = xy[1];
63030             dr.constrainTo(constrainTo);
63031
63032             return [dr.left, dr.top];
63033         },
63034
63035         
63036         dragTarget: function(me, xy) {
63037             var s = me.startXY,
63038                 dr = me.startRegion.copy(),
63039                 constrainTo = me.getConstrainRegion(),
63040                 adjust;
63041
63042             
63043             if (!constrainTo) {
63044                 return xy;
63045             }
63046
63047             
63048             
63049             
63050             dr.translateBy(xy[0]-s[0], xy[1]-s[1]);
63051
63052             
63053             if (dr.right > constrainTo.right) {
63054                 xy[0] += adjust = (constrainTo.right - dr.right);    
63055                 dr.left += adjust;
63056             }
63057             if (dr.left < constrainTo.left) {
63058                 xy[0] += (constrainTo.left - dr.left);      
63059             }
63060
63061             
63062             if (dr.bottom > constrainTo.bottom) {
63063                 xy[1] += adjust = (constrainTo.bottom - dr.bottom);  
63064                 dr.top += adjust;
63065             }
63066             if (dr.top < constrainTo.top) {
63067                 xy[1] += (constrainTo.top - dr.top);        
63068             }
63069             return xy;
63070         }
63071     }
63072 });
63073
63074 Ext.define('Ext.dd.DragZone', {
63075
63076     extend: 'Ext.dd.DragSource',
63077
63078     
63079     constructor : function(el, config){
63080         this.callParent([el, config]);
63081         if (this.containerScroll) {
63082             Ext.dd.ScrollManager.register(this.el);
63083         }
63084     },
63085
63086     
63087
63088     
63089
63090     
63091     getDragData : function(e){
63092         return Ext.dd.Registry.getHandleFromEvent(e);
63093     },
63094
63095     
63096     onInitDrag : function(x, y){
63097         this.proxy.update(this.dragData.ddel.cloneNode(true));
63098         this.onStartDrag(x, y);
63099         return true;
63100     },
63101
63102     
63103     afterRepair : function(){
63104         var me = this;
63105         if (Ext.enableFx) {
63106             Ext.fly(me.dragData.ddel).highlight(me.repairHighlightColor);
63107         }
63108         me.dragging = false;
63109     },
63110
63111     
63112     getRepairXY : function(e){
63113         return Ext.Element.fly(this.dragData.ddel).getXY();
63114     },
63115
63116     destroy : function(){
63117         this.callParent();
63118         if (this.containerScroll) {
63119             Ext.dd.ScrollManager.unregister(this.el);
63120         }
63121     }
63122 });
63123
63124
63125 Ext.define('Ext.dd.ScrollManager', {
63126     singleton: true,
63127     requires: [
63128         'Ext.dd.DragDropManager'
63129     ],
63130
63131     constructor: function() {
63132         var ddm = Ext.dd.DragDropManager;
63133         ddm.fireEvents = Ext.Function.createSequence(ddm.fireEvents, this.onFire, this);
63134         ddm.stopDrag = Ext.Function.createSequence(ddm.stopDrag, this.onStop, this);
63135         this.doScroll = Ext.Function.bind(this.doScroll, this);
63136         this.ddmInstance = ddm;
63137         this.els = {};
63138         this.dragEl = null;
63139         this.proc = {};
63140     },
63141
63142     onStop: function(e){
63143         var sm = Ext.dd.ScrollManager;
63144         sm.dragEl = null;
63145         sm.clearProc();
63146     },
63147
63148     triggerRefresh: function() {
63149         if (this.ddmInstance.dragCurrent) {
63150             this.ddmInstance.refreshCache(this.ddmInstance.dragCurrent.groups);
63151         }
63152     },
63153
63154     doScroll: function() {
63155         if (this.ddmInstance.dragCurrent) {
63156             var proc   = this.proc,
63157                 procEl = proc.el,
63158                 ddScrollConfig = proc.el.ddScrollConfig,
63159                 inc = ddScrollConfig ? ddScrollConfig.increment : this.increment;
63160
63161             if (!this.animate) {
63162                 if (procEl.scroll(proc.dir, inc)) {
63163                     this.triggerRefresh();
63164                 }
63165             } else {
63166                 procEl.scroll(proc.dir, inc, true, this.animDuration, this.triggerRefresh);
63167             }
63168         }
63169     },
63170
63171     clearProc: function() {
63172         var proc = this.proc;
63173         if (proc.id) {
63174             clearInterval(proc.id);
63175         }
63176         proc.id = 0;
63177         proc.el = null;
63178         proc.dir = "";
63179     },
63180
63181     startProc: function(el, dir) {
63182         this.clearProc();
63183         this.proc.el = el;
63184         this.proc.dir = dir;
63185         var group = el.ddScrollConfig ? el.ddScrollConfig.ddGroup : undefined,
63186             freq  = (el.ddScrollConfig && el.ddScrollConfig.frequency)
63187                   ? el.ddScrollConfig.frequency
63188                   : this.frequency;
63189
63190         if (group === undefined || this.ddmInstance.dragCurrent.ddGroup == group) {
63191             this.proc.id = setInterval(this.doScroll, freq);
63192         }
63193     },
63194
63195     onFire: function(e, isDrop) {
63196         if (isDrop || !this.ddmInstance.dragCurrent) {
63197             return;
63198         }
63199         if (!this.dragEl || this.dragEl != this.ddmInstance.dragCurrent) {
63200             this.dragEl = this.ddmInstance.dragCurrent;
63201             
63202             this.refreshCache();
63203         }
63204
63205         var xy = e.getXY(),
63206             pt = e.getPoint(),
63207             proc = this.proc,
63208             els = this.els;
63209
63210         for (var id in els) {
63211             var el = els[id], r = el._region;
63212             var c = el.ddScrollConfig ? el.ddScrollConfig : this;
63213             if (r && r.contains(pt) && el.isScrollable()) {
63214                 if (r.bottom - pt.y <= c.vthresh) {
63215                     if(proc.el != el){
63216                         this.startProc(el, "down");
63217                     }
63218                     return;
63219                 }else if (r.right - pt.x <= c.hthresh) {
63220                     if (proc.el != el) {
63221                         this.startProc(el, "left");
63222                     }
63223                     return;
63224                 } else if(pt.y - r.top <= c.vthresh) {
63225                     if (proc.el != el) {
63226                         this.startProc(el, "up");
63227                     }
63228                     return;
63229                 } else if(pt.x - r.left <= c.hthresh) {
63230                     if (proc.el != el) {
63231                         this.startProc(el, "right");
63232                     }
63233                     return;
63234                 }
63235             }
63236         }
63237         this.clearProc();
63238     },
63239
63240     
63241     register : function(el){
63242         if (Ext.isArray(el)) {
63243             for(var i = 0, len = el.length; i < len; i++) {
63244                     this.register(el[i]);
63245             }
63246         } else {
63247             el = Ext.get(el);
63248             this.els[el.id] = el;
63249         }
63250     },
63251
63252     
63253     unregister : function(el){
63254         if(Ext.isArray(el)){
63255             for (var i = 0, len = el.length; i < len; i++) {
63256                 this.unregister(el[i]);
63257             }
63258         }else{
63259             el = Ext.get(el);
63260             delete this.els[el.id];
63261         }
63262     },
63263
63264     
63265     vthresh : 25,
63266     
63267     hthresh : 25,
63268
63269     
63270     increment : 100,
63271
63272     
63273     frequency : 500,
63274
63275     
63276     animate: true,
63277
63278     
63279     animDuration: 0.4,
63280
63281     
63282     ddGroup: undefined,
63283
63284     
63285     refreshCache : function(){
63286         var els = this.els,
63287             id;
63288         for (id in els) {
63289             if(typeof els[id] == 'object'){ 
63290                 els[id]._region = els[id].getRegion();
63291             }
63292         }
63293     }
63294 });
63295
63296
63297 Ext.define('Ext.dd.DropTarget', {
63298     extend: 'Ext.dd.DDTarget',
63299     requires: ['Ext.dd.ScrollManager'],
63300
63301     
63302     constructor : function(el, config){
63303         this.el = Ext.get(el);
63304
63305         Ext.apply(this, config);
63306
63307         if(this.containerScroll){
63308             Ext.dd.ScrollManager.register(this.el);
63309         }
63310
63311         this.callParent([this.el.dom, this.ddGroup || this.group,
63312               {isTarget: true}]);
63313     },
63314
63315     
63316     
63317     
63318     dropAllowed : Ext.baseCSSPrefix + 'dd-drop-ok',
63319     
63320     dropNotAllowed : Ext.baseCSSPrefix + 'dd-drop-nodrop',
63321
63322     
63323     isTarget : true,
63324
63325     
63326     isNotifyTarget : true,
63327
63328     
63329     notifyEnter : function(dd, e, data){
63330         if(this.overClass){
63331             this.el.addCls(this.overClass);
63332         }
63333         return this.dropAllowed;
63334     },
63335
63336     
63337     notifyOver : function(dd, e, data){
63338         return this.dropAllowed;
63339     },
63340
63341     
63342     notifyOut : function(dd, e, data){
63343         if(this.overClass){
63344             this.el.removeCls(this.overClass);
63345         }
63346     },
63347
63348     
63349     notifyDrop : function(dd, e, data){
63350         return false;
63351     },
63352
63353     destroy : function(){
63354         this.callParent();
63355         if(this.containerScroll){
63356             Ext.dd.ScrollManager.unregister(this.el);
63357         }
63358     }
63359 });
63360
63361
63362 Ext.define('Ext.dd.Registry', {
63363     singleton: true,
63364     constructor: function() {
63365         this.elements = {}; 
63366         this.handles = {}; 
63367         this.autoIdSeed = 0;
63368     },
63369     
63370     getId: function(el, autogen){
63371         if(typeof el == "string"){
63372             return el;
63373         }
63374         var id = el.id;
63375         if(!id && autogen !== false){
63376             id = "extdd-" + (++this.autoIdSeed);
63377             el.id = id;
63378         }
63379         return id;
63380     },
63381     
63382     
63383     register : function(el, data){
63384         data = data || {};
63385         if (typeof el == "string") {
63386             el = document.getElementById(el);
63387         }
63388         data.ddel = el;
63389         this.elements[this.getId(el)] = data;
63390         if (data.isHandle !== false) {
63391             this.handles[data.ddel.id] = data;
63392         }
63393         if (data.handles) {
63394             var hs = data.handles;
63395             for (var i = 0, len = hs.length; i < len; i++) {
63396                 this.handles[this.getId(hs[i])] = data;
63397             }
63398         }
63399     },
63400
63401     
63402     unregister : function(el){
63403         var id = this.getId(el, false);
63404         var data = this.elements[id];
63405         if(data){
63406             delete this.elements[id];
63407             if(data.handles){
63408                 var hs = data.handles;
63409                 for (var i = 0, len = hs.length; i < len; i++) {
63410                     delete this.handles[this.getId(hs[i], false)];
63411                 }
63412             }
63413         }
63414     },
63415
63416     
63417     getHandle : function(id){
63418         if(typeof id != "string"){ 
63419             id = id.id;
63420         }
63421         return this.handles[id];
63422     },
63423
63424     
63425     getHandleFromEvent : function(e){
63426         var t = e.getTarget();
63427         return t ? this.handles[t.id] : null;
63428     },
63429
63430     
63431     getTarget : function(id){
63432         if(typeof id != "string"){ 
63433             id = id.id;
63434         }
63435         return this.elements[id];
63436     },
63437
63438     
63439     getTargetFromEvent : function(e){
63440         var t = e.getTarget();
63441         return t ? this.elements[t.id] || this.handles[t.id] : null;
63442     }
63443 });
63444
63445 Ext.define('Ext.dd.DropZone', {
63446     extend: 'Ext.dd.DropTarget',
63447     requires: ['Ext.dd.Registry'],
63448
63449     
63450     getTargetFromEvent : function(e){
63451         return Ext.dd.Registry.getTargetFromEvent(e);
63452     },
63453
63454     
63455     onNodeEnter : function(n, dd, e, data){
63456         
63457     },
63458
63459     
63460     onNodeOver : function(n, dd, e, data){
63461         return this.dropAllowed;
63462     },
63463
63464     
63465     onNodeOut : function(n, dd, e, data){
63466         
63467     },
63468
63469     
63470     onNodeDrop : function(n, dd, e, data){
63471         return false;
63472     },
63473
63474     
63475     onContainerOver : function(dd, e, data){
63476         return this.dropNotAllowed;
63477     },
63478
63479     
63480     onContainerDrop : function(dd, e, data){
63481         return false;
63482     },
63483
63484     
63485     notifyEnter : function(dd, e, data){
63486         return this.dropNotAllowed;
63487     },
63488
63489     
63490     notifyOver : function(dd, e, data){
63491         var n = this.getTargetFromEvent(e);
63492         if(!n) { 
63493             if(this.lastOverNode){
63494                 this.onNodeOut(this.lastOverNode, dd, e, data);
63495                 this.lastOverNode = null;
63496             }
63497             return this.onContainerOver(dd, e, data);
63498         }
63499         if(this.lastOverNode != n){
63500             if(this.lastOverNode){
63501                 this.onNodeOut(this.lastOverNode, dd, e, data);
63502             }
63503             this.onNodeEnter(n, dd, e, data);
63504             this.lastOverNode = n;
63505         }
63506         return this.onNodeOver(n, dd, e, data);
63507     },
63508
63509     
63510     notifyOut : function(dd, e, data){
63511         if(this.lastOverNode){
63512             this.onNodeOut(this.lastOverNode, dd, e, data);
63513             this.lastOverNode = null;
63514         }
63515     },
63516
63517     
63518     notifyDrop : function(dd, e, data){
63519         if(this.lastOverNode){
63520             this.onNodeOut(this.lastOverNode, dd, e, data);
63521             this.lastOverNode = null;
63522         }
63523         var n = this.getTargetFromEvent(e);
63524         return n ?
63525             this.onNodeDrop(n, dd, e, data) :
63526             this.onContainerDrop(dd, e, data);
63527     },
63528
63529     
63530     triggerCacheRefresh : function() {
63531         Ext.dd.DDM.refreshCache(this.groups);
63532     }
63533 });
63534
63535 Ext.define('Ext.flash.Component', {
63536     extend: 'Ext.Component',
63537     alternateClassName: 'Ext.FlashComponent',
63538     alias: 'widget.flash',
63539
63540     
63541     flashVersion : '9.0.115',
63542
63543     
63544     backgroundColor: '#ffffff',
63545
63546     
63547     wmode: 'opaque',
63548
63549     
63550
63551     
63552
63553     
63554
63555     
63556
63557     
63558     swfWidth: '100%',
63559
63560     
63561     swfHeight: '100%',
63562
63563     
63564     expressInstall: false,
63565
63566     
63567
63568     
63569     renderTpl: ['<div id="{swfId}"></div>'],
63570
63571     initComponent: function() {
63572
63573         this.callParent();
63574         this.addEvents(
63575             
63576             'success',
63577
63578             
63579             'failure'
63580         );
63581     },
63582
63583     onRender: function() {
63584         var me = this,
63585             params, vars, undef,
63586             swfId = me.getSwfId();
63587
63588         me.renderData.swfId = swfId;
63589
63590         me.callParent(arguments);
63591
63592         params = Ext.apply({
63593             allowScriptAccess: 'always',
63594             bgcolor: me.backgroundColor,
63595             wmode: me.wmode
63596         }, me.flashParams);
63597
63598         vars = Ext.apply({
63599             allowedDomain: document.location.hostname
63600         }, me.flashVars);
63601
63602         new swfobject.embedSWF(
63603             me.url,
63604             swfId,
63605             me.swfWidth,
63606             me.swfHeight,
63607             me.flashVersion,
63608             me.expressInstall ? me.statics.EXPRESS_INSTALL_URL : undef,
63609             vars,
63610             params,
63611             me.flashAttributes,
63612             Ext.bind(me.swfCallback, me)
63613         );
63614     },
63615
63616     
63617     swfCallback: function(e) {
63618         var me = this;
63619         if (e.success) {
63620             me.swf = Ext.get(e.ref);
63621             me.onSuccess();
63622             me.fireEvent('success', me);
63623         } else {
63624             me.onFailure();
63625             me.fireEvent('failure', me);
63626         }
63627     },
63628
63629     
63630     getSwfId: function() {
63631         return this.swfId || (this.swfId = "extswf" + this.getAutoId());
63632     },
63633
63634     onSuccess: function() {
63635         
63636         
63637         this.swf.setStyle('visibility', 'inherit');
63638     },
63639
63640     onFailure: Ext.emptyFn,
63641
63642     beforeDestroy: function() {
63643         var me = this,
63644             swf = me.swf;
63645         if (swf) {
63646             swfobject.removeSWF(me.getSwfId());
63647             Ext.destroy(swf);
63648             delete me.swf;
63649         }
63650         me.callParent();
63651     },
63652
63653     statics: {
63654         
63655         EXPRESS_INSTALL_URL: 'http:/' + '/swfobject.googlecode.com/svn/trunk/swfobject/expressInstall.swf'
63656     }
63657 });
63658
63659
63660 Ext.define('Ext.form.action.Action', {
63661     alternateClassName: 'Ext.form.Action',
63662
63663     
63664
63665     
63666
63667     
63668
63669     
63670
63671     
63672
63673     
63674
63675     
63676
63677     
63678
63679     
63680
63681     
63682
63683     
63684
63685     
63686
63687     
63688     submitEmptyText : true,
63689     
63690
63691     
63692
63693     
63694
63695     
63696
63697     
63698     constructor: function(config) {
63699         if (config) {
63700             Ext.apply(this, config);
63701         }
63702
63703         
63704         var params = config.params;
63705         if (Ext.isString(params)) {
63706             this.params = Ext.Object.fromQueryString(params);
63707         }
63708     },
63709
63710     
63711     run: Ext.emptyFn,
63712
63713     
63714
63715     
63716
63717     
63718     onFailure : function(response){
63719         this.response = response;
63720         this.failureType = Ext.form.action.Action.CONNECT_FAILURE;
63721         this.form.afterAction(this, false);
63722     },
63723
63724     
63725     processResponse : function(response){
63726         this.response = response;
63727         if (!response.responseText && !response.responseXML) {
63728             return true;
63729         }
63730         return (this.result = this.handleResponse(response));
63731     },
63732
63733     
63734     getUrl: function() {
63735         return this.url || this.form.url;
63736     },
63737
63738     
63739     getMethod: function() {
63740         return (this.method || this.form.method || 'POST').toUpperCase();
63741     },
63742
63743     
63744     getParams: function() {
63745         return Ext.apply({}, this.params, this.form.baseParams);
63746     },
63747
63748     
63749     createCallback: function() {
63750         var me = this,
63751             undef,
63752             form = me.form;
63753         return {
63754             success: me.onSuccess,
63755             failure: me.onFailure,
63756             scope: me,
63757             timeout: (this.timeout * 1000) || (form.timeout * 1000),
63758             upload: form.fileUpload ? me.onSuccess : undef
63759         };
63760     },
63761
63762     statics: {
63763         
63764         CLIENT_INVALID: 'client',
63765
63766         
63767         SERVER_INVALID: 'server',
63768
63769         
63770         CONNECT_FAILURE: 'connect',
63771
63772         
63773         LOAD_FAILURE: 'load'
63774
63775
63776     }
63777 });
63778
63779
63780 Ext.define('Ext.form.action.Submit', {
63781     extend:'Ext.form.action.Action',
63782     alternateClassName: 'Ext.form.Action.Submit',
63783     alias: 'formaction.submit',
63784
63785     type: 'submit',
63786
63787     
63788
63789     
63790     run : function(){
63791         var form = this.form;
63792         if (this.clientValidation === false || form.isValid()) {
63793             this.doSubmit();
63794         } else {
63795             
63796             this.failureType = Ext.form.action.Action.CLIENT_INVALID;
63797             form.afterAction(this, false);
63798         }
63799     },
63800
63801     
63802     doSubmit: function() {
63803         var formEl,
63804             ajaxOptions = Ext.apply(this.createCallback(), {
63805                 url: this.getUrl(),
63806                 method: this.getMethod(),
63807                 headers: this.headers
63808             });
63809
63810         
63811         
63812         if (this.form.hasUpload()) {
63813             formEl = ajaxOptions.form = this.buildForm();
63814             ajaxOptions.isUpload = true;
63815         } else {
63816             ajaxOptions.params = this.getParams();
63817         }
63818
63819         Ext.Ajax.request(ajaxOptions);
63820
63821         if (formEl) {
63822             Ext.removeNode(formEl);
63823         }
63824     },
63825
63826     
63827     getParams: function() {
63828         var nope = false,
63829             configParams = this.callParent(),
63830             fieldParams = this.form.getValues(nope, nope, this.submitEmptyText !== nope);
63831         return Ext.apply({}, fieldParams, configParams);
63832     },
63833
63834     
63835     buildForm: function() {
63836         var fieldsSpec = [],
63837             formSpec,
63838             formEl,
63839             basicForm = this.form,
63840             params = this.getParams(),
63841             uploadFields = [];
63842
63843         basicForm.getFields().each(function(field) {
63844             if (field.isFileUpload()) {
63845                 uploadFields.push(field);
63846             }
63847         });
63848
63849         function addField(name, val) {
63850             fieldsSpec.push({
63851                 tag: 'input',
63852                 type: 'hidden',
63853                 name: name,
63854                 value: Ext.String.htmlEncode(val)
63855             });
63856         }
63857
63858         
63859         Ext.iterate(params, function(key, val) {
63860             if (Ext.isArray(val)) {
63861                 Ext.each(val, function(v) {
63862                     addField(key, v);
63863                 });
63864             } else {
63865                 addField(key, val);
63866             }
63867         });
63868
63869         formSpec = {
63870             tag: 'form',
63871             action: this.getUrl(),
63872             method: this.getMethod(),
63873             target: this.target || '_self',
63874             style: 'display:none',
63875             cn: fieldsSpec
63876         };
63877
63878         
63879         if (uploadFields.length) {
63880             formSpec.encoding = formSpec.enctype = 'multipart/form-data';
63881         }
63882
63883         
63884         formEl = Ext.DomHelper.append(Ext.getBody(), formSpec);
63885
63886         
63887         
63888         
63889         Ext.Array.each(uploadFields, function(field) {
63890             if (field.rendered) { 
63891                 formEl.appendChild(field.extractFileInput());
63892             }
63893         });
63894
63895         return formEl;
63896     },
63897
63898
63899
63900     
63901     onSuccess: function(response) {
63902         var form = this.form,
63903             success = true,
63904             result = this.processResponse(response);
63905         if (result !== true && !result.success) {
63906             if (result.errors) {
63907                 form.markInvalid(result.errors);
63908             }
63909             this.failureType = Ext.form.action.Action.SERVER_INVALID;
63910             success = false;
63911         }
63912         form.afterAction(this, success);
63913     },
63914
63915     
63916     handleResponse: function(response) {
63917         var form = this.form,
63918             errorReader = form.errorReader,
63919             rs, errors, i, len, records;
63920         if (errorReader) {
63921             rs = errorReader.read(response);
63922             records = rs.records;
63923             errors = [];
63924             if (records) {
63925                 for(i = 0, len = records.length; i < len; i++) {
63926                     errors[i] = records[i].data;
63927                 }
63928             }
63929             if (errors.length < 1) {
63930                 errors = null;
63931             }
63932             return {
63933                 success : rs.success,
63934                 errors : errors
63935             };
63936         }
63937         return Ext.decode(response.responseText);
63938     }
63939 });
63940
63941
63942 Ext.define('Ext.util.ComponentDragger', {
63943
63944     
63945
63946     
63947
63948     
63949
63950     extend: 'Ext.dd.DragTracker',
63951
63952     autoStart: 500,
63953
63954     
63955     constructor: function(comp, config) {
63956         this.comp = comp;
63957         this.initialConstrainTo = config.constrainTo;
63958         this.callParent([ config ]);
63959     },
63960
63961     onStart: function(e) {
63962         var me = this,
63963             comp = me.comp;
63964
63965         
63966         this.startPosition = comp.getPosition();
63967
63968         
63969         
63970         if (comp.ghost && !comp.liveDrag) {
63971              me.proxy = comp.ghost();
63972              me.dragTarget = me.proxy.header.el;
63973         }
63974
63975         
63976         if (me.constrain || me.constrainDelegate) {
63977             me.constrainTo = me.calculateConstrainRegion();
63978         }
63979     },
63980
63981     calculateConstrainRegion: function() {
63982         var me = this,
63983             comp = me.comp,
63984             c = me.initialConstrainTo,
63985             delegateRegion,
63986             elRegion,
63987             shadowSize = comp.el.shadow ? comp.el.shadow.offset : 0;
63988
63989         
63990         if (!(c instanceof Ext.util.Region)) {
63991             c =  Ext.fly(c).getViewRegion();
63992         }
63993
63994         
63995         if (shadowSize) {
63996             c.adjust(0, -shadowSize, -shadowSize, shadowSize);
63997         }
63998
63999         
64000         
64001         
64002         if (!me.constrainDelegate) {
64003             delegateRegion = Ext.fly(me.dragTarget).getRegion();
64004             elRegion = me.proxy ? me.proxy.el.getRegion() : comp.el.getRegion();
64005
64006             c.adjust(
64007                 delegateRegion.top - elRegion.top,
64008                 delegateRegion.right - elRegion.right,
64009                 delegateRegion.bottom - elRegion.bottom,
64010                 delegateRegion.left - elRegion.left
64011             );
64012         }
64013         return c;
64014     },
64015
64016     
64017     onDrag: function(e) {
64018         var me = this,
64019             comp = (me.proxy && !me.comp.liveDrag) ? me.proxy : me.comp,
64020             offset = me.getOffset(me.constrain || me.constrainDelegate ? 'dragTarget' : null);
64021
64022         comp.setPosition(me.startPosition[0] + offset[0], me.startPosition[1] + offset[1]);
64023     },
64024
64025     onEnd: function(e) {
64026         if (this.proxy && !this.comp.liveDrag) {
64027             this.comp.unghost();
64028         }
64029     }
64030 });
64031
64032 Ext.define("Ext.form.Labelable", {
64033     requires: ['Ext.XTemplate'],
64034
64035     
64036     labelableRenderTpl: [
64037         '<tpl if="!hideLabel && !(!fieldLabel && hideEmptyLabel)">',
64038             '<label id="{id}-labelEl"<tpl if="inputId"> for="{inputId}"</tpl> class="{labelCls}"',
64039                 '<tpl if="labelStyle"> style="{labelStyle}"</tpl>>',
64040                 '<tpl if="fieldLabel">{fieldLabel}{labelSeparator}</tpl>',
64041             '</label>',
64042         '</tpl>',
64043         '<div class="{baseBodyCls} {fieldBodyCls}" id="{id}-bodyEl" role="presentation">{subTplMarkup}</div>',
64044         '<div id="{id}-errorEl" class="{errorMsgCls}" style="display:none"></div>',
64045         '<div class="{clearCls}" role="presentation"><!-- --></div>',
64046         {
64047             compiled: true,
64048             disableFormats: true
64049         }
64050     ],
64051
64052     
64053     activeErrorsTpl: [
64054         '<tpl if="errors && errors.length">',
64055             '<ul><tpl for="errors"><li<tpl if="xindex == xcount"> class="last"</tpl>>{.}</li></tpl></ul>',
64056         '</tpl>'
64057     ],
64058
64059     
64060     isFieldLabelable: true,
64061
64062     
64063     formItemCls: Ext.baseCSSPrefix + 'form-item',
64064
64065     
64066     labelCls: Ext.baseCSSPrefix + 'form-item-label',
64067
64068     
64069
64070     
64071     errorMsgCls: Ext.baseCSSPrefix + 'form-error-msg',
64072
64073     
64074     baseBodyCls: Ext.baseCSSPrefix + 'form-item-body',
64075
64076     
64077     fieldBodyCls: '',
64078
64079     
64080     clearCls: Ext.baseCSSPrefix + 'clear',
64081
64082     
64083     invalidCls : Ext.baseCSSPrefix + 'form-invalid',
64084
64085     
64086     fieldLabel: undefined,
64087
64088     
64089     labelAlign : 'left',
64090
64091     
64092     labelWidth: 100,
64093
64094     
64095     labelPad : 5,
64096
64097     
64098     labelSeparator : ':',
64099
64100     
64101
64102     
64103     hideLabel: false,
64104
64105     
64106     hideEmptyLabel: true,
64107
64108     
64109     preventMark: false,
64110
64111     
64112     autoFitErrors: true,
64113
64114     
64115     msgTarget: 'qtip',
64116
64117     
64118
64119
64120     
64121     initLabelable: function() {
64122         this.addCls(this.formItemCls);
64123
64124         this.addEvents(
64125             
64126             'errorchange'
64127         );
64128     },
64129
64130     
64131     getFieldLabel: function() {
64132         return this.fieldLabel || '';
64133     },
64134
64135     
64136     getLabelableRenderData: function() {
64137         var me = this,
64138             labelAlign = me.labelAlign,
64139             labelCls = me.labelCls,
64140             labelClsExtra = me.labelClsExtra,
64141             labelPad = me.labelPad,
64142             labelStyle;
64143
64144         
64145         
64146         if (labelAlign === 'top') {
64147             labelStyle = 'margin-bottom:' + labelPad + 'px;';
64148         } else {
64149             labelStyle = 'margin-right:' + labelPad + 'px;';
64150             
64151             if (Ext.isBorderBox) {
64152                 labelStyle += 'width:' + me.labelWidth + 'px;';
64153             }
64154         }
64155
64156         return Ext.copyTo(
64157             {
64158                 inputId: me.getInputId(),
64159                 fieldLabel: me.getFieldLabel(),
64160                 labelCls: labelClsExtra ? labelCls + ' ' + labelClsExtra : labelCls,
64161                 labelStyle: labelStyle + (me.labelStyle || ''),
64162                 subTplMarkup: me.getSubTplMarkup()
64163             },
64164             me,
64165             'hideLabel,hideEmptyLabel,fieldBodyCls,baseBodyCls,errorMsgCls,clearCls,labelSeparator',
64166             true
64167         );
64168     },
64169
64170     onLabelableRender: function () {
64171         this.addChildEls(
64172             
64173             'labelEl',
64174
64175             
64176             'bodyEl',
64177
64178             
64179             'errorEl'
64180         );
64181     },
64182
64183     
64184     getSubTplMarkup: function() {
64185         return '';
64186     },
64187
64188     
64189     getInputId: function() {
64190         return '';
64191     },
64192
64193     
64194     getActiveError : function() {
64195         return this.activeError || '';
64196     },
64197
64198     
64199     hasActiveError: function() {
64200         return !!this.getActiveError();
64201     },
64202
64203     
64204     setActiveError: function(msg) {
64205         this.activeError = msg;
64206         this.activeErrors = [msg];
64207         this.renderActiveError();
64208     },
64209
64210     
64211     getActiveErrors: function() {
64212         return this.activeErrors || [];
64213     },
64214
64215     
64216     setActiveErrors: function(errors) {
64217         this.activeErrors = errors;
64218         this.activeError = this.getTpl('activeErrorsTpl').apply({errors: errors});
64219         this.renderActiveError();
64220     },
64221
64222     
64223     unsetActiveError: function() {
64224         delete this.activeError;
64225         delete this.activeErrors;
64226         this.renderActiveError();
64227     },
64228
64229     
64230     renderActiveError: function() {
64231         var me = this,
64232             activeError = me.getActiveError(),
64233             hasError = !!activeError;
64234
64235         if (activeError !== me.lastActiveError) {
64236             me.fireEvent('errorchange', me, activeError);
64237             me.lastActiveError = activeError;
64238         }
64239
64240         if (me.rendered && !me.isDestroyed && !me.preventMark) {
64241             
64242             me.el[hasError ? 'addCls' : 'removeCls'](me.invalidCls);
64243
64244             
64245             me.getActionEl().dom.setAttribute('aria-invalid', hasError);
64246
64247             
64248             me.errorEl.dom.innerHTML = activeError;
64249         }
64250     },
64251
64252     
64253     setFieldDefaults: function(defaults) {
64254         var me = this;
64255         Ext.iterate(defaults, function(key, val) {
64256             if (!me.hasOwnProperty(key)) {
64257                 me[key] = val;
64258             }
64259         });
64260     },
64261
64262     
64263     getBodyNaturalWidth: function() {
64264         return this.bodyEl.getWidth();
64265     }
64266
64267 });
64268
64269
64270 Ext.define('Ext.form.field.Field', {
64271     
64272     isFormField : true,
64273
64274     
64275
64276     
64277
64278     
64279     disabled : false,
64280
64281     
64282     submitValue: true,
64283
64284     
64285     validateOnChange: true,
64286
64287     
64288     suspendCheckChange: 0,
64289
64290     
64291     initField: function() {
64292         this.addEvents(
64293             
64294             'change',
64295             
64296             'validitychange',
64297             
64298             'dirtychange'
64299         );
64300
64301         this.initValue();
64302     },
64303
64304     
64305     initValue: function() {
64306         var me = this;
64307
64308         
64309         me.originalValue = me.lastValue = me.value;
64310
64311         
64312         me.suspendCheckChange++;
64313         me.setValue(me.value);
64314         me.suspendCheckChange--;
64315     },
64316
64317     
64318     getName: function() {
64319         return this.name;
64320     },
64321
64322     
64323     getValue: function() {
64324         return this.value;
64325     },
64326
64327     
64328     setValue: function(value) {
64329         var me = this;
64330         me.value = value;
64331         me.checkChange();
64332         return me;
64333     },
64334
64335     
64336     isEqual: function(value1, value2) {
64337         return String(value1) === String(value2);
64338     },
64339     
64340     
64341     isEqualAsString: function(value1, value2){
64342         return String(Ext.value(value1, '')) === String(Ext.value(value2, ''));    
64343     },
64344
64345     
64346     getSubmitData: function() {
64347         var me = this,
64348             data = null;
64349         if (!me.disabled && me.submitValue && !me.isFileUpload()) {
64350             data = {};
64351             data[me.getName()] = '' + me.getValue();
64352         }
64353         return data;
64354     },
64355
64356     
64357     getModelData: function() {
64358         var me = this,
64359             data = null;
64360         if (!me.disabled && !me.isFileUpload()) {
64361             data = {};
64362             data[me.getName()] = me.getValue();
64363         }
64364         return data;
64365     },
64366
64367     
64368     reset : function(){
64369         var me = this;
64370
64371         me.setValue(me.originalValue);
64372         me.clearInvalid();
64373         
64374         delete me.wasValid;
64375     },
64376
64377     
64378     resetOriginalValue: function() {
64379         this.originalValue = this.getValue();
64380         this.checkDirty();
64381     },
64382
64383     
64384     checkChange: function() {
64385         if (!this.suspendCheckChange) {
64386             var me = this,
64387                 newVal = me.getValue(),
64388                 oldVal = me.lastValue;
64389             if (!me.isEqual(newVal, oldVal) && !me.isDestroyed) {
64390                 me.lastValue = newVal;
64391                 me.fireEvent('change', me, newVal, oldVal);
64392                 me.onChange(newVal, oldVal);
64393             }
64394         }
64395     },
64396
64397     
64398     onChange: function(newVal, oldVal) {
64399         if (this.validateOnChange) {
64400             this.validate();
64401         }
64402         this.checkDirty();
64403     },
64404
64405     
64406     isDirty : function() {
64407         var me = this;
64408         return !me.disabled && !me.isEqual(me.getValue(), me.originalValue);
64409     },
64410
64411     
64412     checkDirty: function() {
64413         var me = this,
64414             isDirty = me.isDirty();
64415         if (isDirty !== me.wasDirty) {
64416             me.fireEvent('dirtychange', me, isDirty);
64417             me.onDirtyChange(isDirty);
64418             me.wasDirty = isDirty;
64419         }
64420     },
64421
64422     
64423     onDirtyChange: Ext.emptyFn,
64424
64425     
64426     getErrors: function(value) {
64427         return [];
64428     },
64429
64430     
64431     isValid : function() {
64432         var me = this;
64433         return me.disabled || Ext.isEmpty(me.getErrors());
64434     },
64435
64436     
64437     validate : function() {
64438         var me = this,
64439             isValid = me.isValid();
64440         if (isValid !== me.wasValid) {
64441             me.wasValid = isValid;
64442             me.fireEvent('validitychange', me, isValid);
64443         }
64444         return isValid;
64445     },
64446
64447     
64448     batchChanges: function(fn) {
64449         try {
64450             this.suspendCheckChange++;
64451             fn();
64452         } catch(e){
64453             throw e;
64454         } finally {
64455             this.suspendCheckChange--;
64456         }
64457         this.checkChange();
64458     },
64459
64460     
64461     isFileUpload: function() {
64462         return false;
64463     },
64464
64465     
64466     extractFileInput: function() {
64467         return null;
64468     },
64469
64470     
64471     markInvalid: Ext.emptyFn,
64472
64473     
64474     clearInvalid: Ext.emptyFn
64475
64476 });
64477
64478
64479 Ext.define('Ext.layout.component.field.Field', {
64480
64481     
64482
64483     alias: ['layout.field'],
64484
64485     extend: 'Ext.layout.component.Component',
64486
64487     uses: ['Ext.tip.QuickTip', 'Ext.util.TextMetrics'],
64488
64489     
64490
64491     type: 'field',
64492
64493     beforeLayout: function(width, height) {
64494         var me = this;
64495         return me.callParent(arguments) || (!me.owner.preventMark && me.activeError !== me.owner.getActiveError());
64496     },
64497
64498     onLayout: function(width, height) {
64499         var me = this,
64500             owner = me.owner,
64501             labelStrategy = me.getLabelStrategy(),
64502             errorStrategy = me.getErrorStrategy(),
64503             isDefined = Ext.isDefined,
64504             isNumber = Ext.isNumber,
64505             lastSize, autoWidth, autoHeight, info, undef;
64506
64507         lastSize = me.lastComponentSize || {};
64508         if (!isDefined(width)) {
64509             width = lastSize.width;
64510             if (width < 0) { 
64511                 width = undef;
64512             }
64513         }
64514         if (!isDefined(height)) {
64515             height = lastSize.height;
64516             if (height < 0) { 
64517                 height = undef;
64518             }
64519         }
64520         autoWidth = !isNumber(width);
64521         autoHeight = !isNumber(height);
64522
64523         info = {
64524             autoWidth: autoWidth,
64525             autoHeight: autoHeight,
64526             width: autoWidth ? owner.getBodyNaturalWidth() : width, 
64527             height: height,
64528             setOuterWidth: false, 
64529
64530             
64531             insets: {
64532                 top: 0,
64533                 right: 0,
64534                 bottom: 0,
64535                 left: 0
64536             }
64537         };
64538
64539         
64540         
64541         
64542
64543         
64544         labelStrategy.prepare(owner, info);
64545         errorStrategy.prepare(owner, info);
64546
64547         
64548         labelStrategy.adjustHorizInsets(owner, info);
64549         errorStrategy.adjustHorizInsets(owner, info);
64550
64551         
64552         labelStrategy.layoutHoriz(owner, info);
64553         errorStrategy.layoutHoriz(owner, info);
64554
64555         
64556         labelStrategy.adjustVertInsets(owner, info);
64557         errorStrategy.adjustVertInsets(owner, info);
64558
64559         
64560         labelStrategy.layoutVert(owner, info);
64561         errorStrategy.layoutVert(owner, info);
64562
64563         
64564         if (autoWidth && autoHeight) {
64565             
64566             me.setElementSize(owner.el, (info.setOuterWidth ? info.width : undef), info.height);
64567         } else {
64568             me.setTargetSize((!autoWidth || info.setOuterWidth ? info.width : undef), info.height);
64569         }
64570         me.sizeBody(info);
64571
64572         me.activeError = owner.getActiveError();
64573     },
64574     
64575     onFocus: function(){
64576         this.getErrorStrategy().onFocus(this.owner);    
64577     },
64578
64579
64580     
64581     sizeBody: function(info) {
64582         var me = this,
64583             owner = me.owner,
64584             insets = info.insets,
64585             totalWidth = info.width,
64586             totalHeight = info.height,
64587             width = Ext.isNumber(totalWidth) ? totalWidth - insets.left - insets.right : totalWidth,
64588             height = Ext.isNumber(totalHeight) ? totalHeight - insets.top - insets.bottom : totalHeight;
64589
64590         
64591         me.setElementSize(owner.bodyEl, width, height);
64592
64593         
64594         me.sizeBodyContents(width, height);
64595     },
64596
64597     
64598     sizeBodyContents: Ext.emptyFn,
64599
64600
64601     
64602     getLabelStrategy: function() {
64603         var me = this,
64604             strategies = me.labelStrategies,
64605             labelAlign = me.owner.labelAlign;
64606         return strategies[labelAlign] || strategies.base;
64607     },
64608
64609     
64610     getErrorStrategy: function() {
64611         var me = this,
64612             owner = me.owner,
64613             strategies = me.errorStrategies,
64614             msgTarget = owner.msgTarget;
64615         return !owner.preventMark && Ext.isString(msgTarget) ?
64616                 (strategies[msgTarget] || strategies.elementId) :
64617                 strategies.none;
64618     },
64619
64620
64621
64622     
64623     labelStrategies: (function() {
64624         var applyIf = Ext.applyIf,
64625             emptyFn = Ext.emptyFn,
64626             base = {
64627                 prepare: function(owner, info) {
64628                     var cls = owner.labelCls + '-' + owner.labelAlign,
64629                         labelEl = owner.labelEl;
64630                     if (labelEl && !labelEl.hasCls(cls)) {
64631                         labelEl.addCls(cls);
64632                     }
64633                 },
64634                 adjustHorizInsets: emptyFn,
64635                 adjustVertInsets: emptyFn,
64636                 layoutHoriz: emptyFn,
64637                 layoutVert: emptyFn
64638             },
64639             left = applyIf({
64640                 prepare: function(owner, info) {
64641                     base.prepare(owner, info);
64642                     
64643                     if (info.autoWidth) {
64644                         info.width += (!owner.labelEl ? 0 : owner.labelWidth + owner.labelPad);
64645                     }
64646                     
64647                     info.setOuterWidth = true;
64648                 },
64649                 adjustHorizInsets: function(owner, info) {
64650                     if (owner.labelEl) {
64651                         info.insets.left += owner.labelWidth + owner.labelPad;
64652                     }
64653                 },
64654                 layoutHoriz: function(owner, info) {
64655                     
64656                     
64657                     
64658                     
64659                     
64660                     var labelEl = owner.labelEl;
64661                     if (labelEl && !owner.isLabelSized && !Ext.isBorderBox) {
64662                         labelEl.setWidth(owner.labelWidth);
64663                         owner.isLabelSized = true;
64664                     }
64665                 }
64666             }, base);
64667
64668
64669         return {
64670             base: base,
64671
64672             
64673             top: applyIf({
64674                 adjustVertInsets: function(owner, info) {
64675                     var labelEl = owner.labelEl;
64676                     if (labelEl) {
64677                         info.insets.top += Ext.util.TextMetrics.measure(labelEl, owner.fieldLabel, info.width).height +
64678                                            labelEl.getFrameWidth('tb') + owner.labelPad;
64679                     }
64680                 }
64681             }, base),
64682
64683             
64684             left: left,
64685
64686             
64687             right: left
64688         };
64689     })(),
64690
64691
64692
64693     
64694     errorStrategies: (function() {
64695         function setDisplayed(el, displayed) {
64696             var wasDisplayed = el.getStyle('display') !== 'none';
64697             if (displayed !== wasDisplayed) {
64698                 el.setDisplayed(displayed);
64699             }
64700         }
64701
64702         function setStyle(el, name, value) {
64703             if (el.getStyle(name) !== value) {
64704                 el.setStyle(name, value);
64705             }
64706         }
64707         
64708         function showTip(owner) {
64709             var tip = Ext.layout.component.field.Field.tip,
64710                 target;
64711                 
64712             if (tip && tip.isVisible()) {
64713                 target = tip.activeTarget;
64714                 if (target && target.el === owner.getActionEl().dom) {
64715                     tip.toFront(true);
64716                 }
64717             }
64718         }
64719
64720         var applyIf = Ext.applyIf,
64721             emptyFn = Ext.emptyFn,
64722             base = {
64723                 prepare: function(owner) {
64724                     setDisplayed(owner.errorEl, false);
64725                 },
64726                 adjustHorizInsets: emptyFn,
64727                 adjustVertInsets: emptyFn,
64728                 layoutHoriz: emptyFn,
64729                 layoutVert: emptyFn,
64730                 onFocus: emptyFn
64731             };
64732
64733         return {
64734             none: base,
64735
64736             
64737             side: applyIf({
64738                 prepare: function(owner) {
64739                     var errorEl = owner.errorEl;
64740                     errorEl.addCls(Ext.baseCSSPrefix + 'form-invalid-icon');
64741                     Ext.layout.component.field.Field.initTip();
64742                     errorEl.dom.setAttribute('data-errorqtip', owner.getActiveError() || '');
64743                     setDisplayed(errorEl, owner.hasActiveError());
64744                 },
64745                 adjustHorizInsets: function(owner, info) {
64746                     if (owner.autoFitErrors && owner.hasActiveError()) {
64747                         info.insets.right += owner.errorEl.getWidth();
64748                     }
64749                 },
64750                 layoutHoriz: function(owner, info) {
64751                     if (owner.hasActiveError()) {
64752                         setStyle(owner.errorEl, 'left', info.width - info.insets.right + 'px');
64753                     }
64754                 },
64755                 layoutVert: function(owner, info) {
64756                     if (owner.hasActiveError()) {
64757                         setStyle(owner.errorEl, 'top', info.insets.top + 'px');
64758                     }
64759                 },
64760                 onFocus: showTip
64761             }, base),
64762
64763             
64764             under: applyIf({
64765                 prepare: function(owner) {
64766                     var errorEl = owner.errorEl,
64767                         cls = Ext.baseCSSPrefix + 'form-invalid-under';
64768                     if (!errorEl.hasCls(cls)) {
64769                         errorEl.addCls(cls);
64770                     }
64771                     setDisplayed(errorEl, owner.hasActiveError());
64772                 },
64773                 adjustVertInsets: function(owner, info) {
64774                     if (owner.autoFitErrors) {
64775                         info.insets.bottom += owner.errorEl.getHeight();
64776                     }
64777                 },
64778                 layoutHoriz: function(owner, info) {
64779                     var errorEl = owner.errorEl,
64780                         insets = info.insets;
64781
64782                     setStyle(errorEl, 'width', info.width - insets.right - insets.left + 'px');
64783                     setStyle(errorEl, 'marginLeft', insets.left + 'px');
64784                 }
64785             }, base),
64786
64787             
64788             qtip: applyIf({
64789                 prepare: function(owner) {
64790                     setDisplayed(owner.errorEl, false);
64791                     Ext.layout.component.field.Field.initTip();
64792                     owner.getActionEl().dom.setAttribute('data-errorqtip', owner.getActiveError() || '');
64793                 },
64794                 onFocus: showTip
64795             }, base),
64796
64797             
64798             title: applyIf({
64799                 prepare: function(owner) {
64800                     setDisplayed(owner.errorEl, false);
64801                     owner.el.dom.title = owner.getActiveError() || '';
64802                 }
64803             }, base),
64804
64805             
64806             elementId: applyIf({
64807                 prepare: function(owner) {
64808                     setDisplayed(owner.errorEl, false);
64809                     var targetEl = Ext.fly(owner.msgTarget);
64810                     if (targetEl) {
64811                         targetEl.dom.innerHTML = owner.getActiveError() || '';
64812                         targetEl.setDisplayed(owner.hasActiveError());
64813                     }
64814                 }
64815             }, base)
64816         };
64817     })(),
64818
64819     statics: {
64820         
64821         initTip: function() {
64822             var tip = this.tip;
64823             if (!tip) {
64824                 tip = this.tip = Ext.create('Ext.tip.QuickTip', {
64825                     baseCls: Ext.baseCSSPrefix + 'form-invalid-tip',
64826                     renderTo: Ext.getBody()
64827                 });
64828                 tip.tagConfig = Ext.apply({}, {attribute: 'errorqtip'}, tip.tagConfig);
64829             }
64830         },
64831
64832         
64833         destroyTip: function() {
64834             var tip = this.tip;
64835             if (tip) {
64836                 tip.destroy();
64837                 delete this.tip;
64838             }
64839         }
64840     }
64841
64842 });
64843
64844
64845 Ext.define('Ext.form.field.VTypes', (function(){
64846     
64847     var alpha = /^[a-zA-Z_]+$/,
64848         alphanum = /^[a-zA-Z0-9_]+$/,
64849         email = /^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/,
64850         url = /(((^https?)|(^ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
64851
64852     
64853     return {
64854         singleton: true,
64855         alternateClassName: 'Ext.form.VTypes',
64856
64857         
64858         'email' : function(v){
64859             return email.test(v);
64860         },
64861         
64862         'emailText' : 'This field should be an e-mail address in the format "user@example.com"',
64863         
64864         'emailMask' : /[a-z0-9_\.\-@\+]/i,
64865
64866         
64867         'url' : function(v){
64868             return url.test(v);
64869         },
64870         
64871         'urlText' : 'This field should be a URL in the format "http:/'+'/www.example.com"',
64872
64873         
64874         'alpha' : function(v){
64875             return alpha.test(v);
64876         },
64877         
64878         'alphaText' : 'This field should only contain letters and _',
64879         
64880         'alphaMask' : /[a-z_]/i,
64881
64882         
64883         'alphanum' : function(v){
64884             return alphanum.test(v);
64885         },
64886         
64887         'alphanumText' : 'This field should only contain letters, numbers and _',
64888         
64889         'alphanumMask' : /[a-z0-9_]/i
64890     };
64891 })());
64892
64893
64894 Ext.define('Ext.layout.component.field.Text', {
64895     extend: 'Ext.layout.component.field.Field',
64896     alias: 'layout.textfield',
64897     requires: ['Ext.util.TextMetrics'],
64898
64899     type: 'textfield',
64900
64901
64902     
64903     beforeLayout: function(width, height) {
64904         var me = this,
64905             owner = me.owner,
64906             lastValue = this.lastValue,
64907             value = owner.getRawValue();
64908         this.lastValue = value;
64909         return me.callParent(arguments) || (owner.grow && value !== lastValue);
64910     },
64911
64912
64913     
64914     sizeBodyContents: function(width, height) {
64915         var size = this.adjustForGrow(width, height);
64916         this.setElementSize(this.owner.inputEl, size[0], size[1]);
64917     },
64918
64919
64920     
64921     adjustForGrow: function(width, height) {
64922         var me = this,
64923             owner = me.owner,
64924             inputEl, value, calcWidth,
64925             result = [width, height];
64926
64927         if (owner.grow) {
64928             inputEl = owner.inputEl;
64929
64930             
64931             value = (inputEl.dom.value || (owner.hasFocus ? '' : owner.emptyText) || '') + owner.growAppend;
64932             calcWidth = inputEl.getTextWidth(value) + inputEl.getBorderWidth("lr") + inputEl.getPadding("lr");
64933
64934             
64935             result[0] = Ext.Number.constrain(calcWidth, owner.growMin,
64936                     Math.max(owner.growMin, Math.min(owner.growMax, Ext.isNumber(width) ? width : Infinity)));
64937         }
64938
64939         return result;
64940     }
64941
64942 });
64943
64944
64945 Ext.define('Ext.layout.component.field.TextArea', {
64946     extend: 'Ext.layout.component.field.Text',
64947     alias: 'layout.textareafield',
64948
64949     type: 'textareafield',
64950
64951
64952     
64953     adjustForGrow: function(width, height) {
64954         var me = this,
64955             owner = me.owner,
64956             inputEl, value, max,
64957             curWidth, curHeight, calcHeight,
64958             result = [width, height];
64959
64960         if (owner.grow) {
64961             inputEl = owner.inputEl;
64962             curWidth = inputEl.getWidth(true); 
64963             curHeight = inputEl.getHeight();
64964
64965             
64966             value = inputEl.dom.value || '&#160;';
64967             value += owner.growAppend;
64968
64969             
64970             value = value.replace(/\n/g, '<br>');
64971
64972             
64973             calcHeight = Ext.util.TextMetrics.measure(inputEl, value, curWidth).height +
64974                          inputEl.getBorderWidth("tb") + inputEl.getPadding("tb");
64975
64976             
64977             max = owner.growMax;
64978             if (Ext.isNumber(height)) {
64979                 max = Math.min(max, height);
64980             }
64981             result[1] = Ext.Number.constrain(calcHeight, owner.growMin, max);
64982         }
64983
64984         return result;
64985     }
64986
64987 });
64988
64989 Ext.define('Ext.layout.container.Anchor', {
64990
64991     
64992
64993     alias: 'layout.anchor',
64994     extend: 'Ext.layout.container.Container',
64995     alternateClassName: 'Ext.layout.AnchorLayout',
64996
64997     
64998
64999     
65000     type: 'anchor',
65001
65002     
65003     defaultAnchor: '100%',
65004
65005     parseAnchorRE: /^(r|right|b|bottom)$/i,
65006
65007     
65008     onLayout: function() {
65009         this.callParent(arguments);
65010
65011         var me = this,
65012             size = me.getLayoutTargetSize(),
65013             owner = me.owner,
65014             target = me.getTarget(),
65015             ownerWidth = size.width,
65016             ownerHeight = size.height,
65017             overflow = target.getStyle('overflow'),
65018             components = me.getVisibleItems(owner),
65019             len = components.length,
65020             boxes = [],
65021             box, newTargetSize, component, anchorSpec, calcWidth, calcHeight,
65022             i, el, cleaner;
65023
65024         if (ownerWidth < 20 && ownerHeight < 20) {
65025             return;
65026         }
65027
65028         
65029         
65030         
65031         if (!me.clearEl) {
65032             me.clearEl = target.createChild({
65033                 cls: Ext.baseCSSPrefix + 'clear',
65034                 role: 'presentation'
65035             });
65036         }
65037
65038         
65039         if (!Ext.supports.RightMargin) {
65040             cleaner = Ext.Element.getRightMarginFixCleaner(target);
65041             target.addCls(Ext.baseCSSPrefix + 'inline-children');
65042         }
65043
65044         for (i = 0; i < len; i++) {
65045             component = components[i];
65046             el = component.el;
65047
65048             anchorSpec = component.anchorSpec;
65049             if (anchorSpec) {
65050                 if (anchorSpec.right) {
65051                     calcWidth = me.adjustWidthAnchor(anchorSpec.right(ownerWidth) - el.getMargin('lr'), component);
65052                 } else {
65053                     calcWidth = undefined;
65054                 }
65055                 if (anchorSpec.bottom) {
65056                     calcHeight = me.adjustHeightAnchor(anchorSpec.bottom(ownerHeight) - el.getMargin('tb'), component);
65057                 } else {
65058                     calcHeight = undefined;
65059                 }
65060
65061                 boxes.push({
65062                     component: component,
65063                     anchor: true,
65064                     width: calcWidth || undefined,
65065                     height: calcHeight || undefined
65066                 });
65067             } else {
65068                 boxes.push({
65069                     component: component,
65070                     anchor: false
65071                 });
65072             }
65073         }
65074
65075         
65076         if (!Ext.supports.RightMargin) {
65077             target.removeCls(Ext.baseCSSPrefix + 'inline-children');
65078             cleaner();
65079         }
65080
65081         for (i = 0; i < len; i++) {
65082             box = boxes[i];
65083             me.setItemSize(box.component, box.width, box.height);
65084         }
65085
65086         if (overflow && overflow != 'hidden' && !me.adjustmentPass) {
65087             newTargetSize = me.getLayoutTargetSize();
65088             if (newTargetSize.width != size.width || newTargetSize.height != size.height) {
65089                 me.adjustmentPass = true;
65090                 me.onLayout();
65091             }
65092         }
65093
65094         delete me.adjustmentPass;
65095     },
65096
65097     
65098     parseAnchor: function(a, start, cstart) {
65099         if (a && a != 'none') {
65100             var ratio;
65101             
65102             if (this.parseAnchorRE.test(a)) {
65103                 var diff = cstart - start;
65104                 return function(v) {
65105                     return v - diff;
65106                 };
65107             }    
65108             
65109             else if (a.indexOf('%') != -1) {
65110                 ratio = parseFloat(a.replace('%', '')) * 0.01;
65111                 return function(v) {
65112                     return Math.floor(v * ratio);
65113                 };
65114             }    
65115             
65116             else {
65117                 a = parseInt(a, 10);
65118                 if (!isNaN(a)) {
65119                     return function(v) {
65120                         return v + a;
65121                     };
65122                 }
65123             }
65124         }
65125         return null;
65126     },
65127
65128     
65129     adjustWidthAnchor: function(value, comp) {
65130         return value;
65131     },
65132
65133     
65134     adjustHeightAnchor: function(value, comp) {
65135         return value;
65136     },
65137
65138     configureItem: function(item) {
65139         var me = this,
65140             owner = me.owner,
65141             anchor= item.anchor,
65142             anchorsArray,
65143             anchorSpec,
65144             anchorWidth,
65145             anchorHeight;
65146
65147         if (!item.anchor && item.items && !Ext.isNumber(item.width) && !(Ext.isIE6 && Ext.isStrict)) {
65148             item.anchor = anchor = me.defaultAnchor;
65149         }
65150
65151         
65152         if (owner.anchorSize) {
65153             if (typeof owner.anchorSize == 'number') {
65154                 anchorWidth = owner.anchorSize;
65155             }
65156             else {
65157                 anchorWidth = owner.anchorSize.width;
65158                 anchorHeight = owner.anchorSize.height;
65159             }
65160         }
65161         else {
65162             anchorWidth = owner.initialConfig.width;
65163             anchorHeight = owner.initialConfig.height;
65164         }
65165
65166         if (anchor) {
65167             
65168             anchorsArray = anchor.split(' ');
65169             item.anchorSpec = anchorSpec = {
65170                 right: me.parseAnchor(anchorsArray[0], item.initialConfig.width, anchorWidth),
65171                 bottom: me.parseAnchor(anchorsArray[1], item.initialConfig.height, anchorHeight)
65172             };
65173
65174             if (anchorSpec.right) {
65175                 item.layoutManagedWidth = 1;
65176             } else {
65177                 item.layoutManagedWidth = 2;
65178             }
65179
65180             if (anchorSpec.bottom) {
65181                 item.layoutManagedHeight = 1;
65182             } else {
65183                 item.layoutManagedHeight = 2;
65184             }
65185         } else {
65186             item.layoutManagedWidth = 2;
65187             item.layoutManagedHeight = 2;
65188         }
65189         this.callParent(arguments);
65190     }
65191
65192 });
65193
65194 Ext.define('Ext.form.action.Load', {
65195     extend:'Ext.form.action.Action',
65196     requires: ['Ext.data.Connection'],
65197     alternateClassName: 'Ext.form.Action.Load',
65198     alias: 'formaction.load',
65199
65200     type: 'load',
65201
65202     
65203     run: function() {
65204         Ext.Ajax.request(Ext.apply(
65205             this.createCallback(),
65206             {
65207                 method: this.getMethod(),
65208                 url: this.getUrl(),
65209                 headers: this.headers,
65210                 params: this.getParams()
65211             }
65212         ));
65213     },
65214
65215     
65216     onSuccess: function(response){
65217         var result = this.processResponse(response),
65218             form = this.form;
65219         if (result === true || !result.success || !result.data) {
65220             this.failureType = Ext.form.action.Action.LOAD_FAILURE;
65221             form.afterAction(this, false);
65222             return;
65223         }
65224         form.clearInvalid();
65225         form.setValues(result.data);
65226         form.afterAction(this, true);
65227     },
65228
65229     
65230     handleResponse: function(response) {
65231         var reader = this.form.reader,
65232             rs, data;
65233         if (reader) {
65234             rs = reader.read(response);
65235             data = rs.records && rs.records[0] ? rs.records[0].data : null;
65236             return {
65237                 success : rs.success,
65238                 data : data
65239             };
65240         }
65241         return Ext.decode(response.responseText);
65242     }
65243 });
65244
65245
65246
65247 Ext.define('Ext.window.Window', {
65248     extend: 'Ext.panel.Panel',
65249
65250     alternateClassName: 'Ext.Window',
65251
65252     requires: ['Ext.util.ComponentDragger', 'Ext.util.Region', 'Ext.EventManager'],
65253
65254     alias: 'widget.window',
65255
65256     
65257
65258     
65259
65260     
65261
65262     
65263
65264     
65265
65266     
65267
65268     
65269
65270     
65271
65272     
65273     baseCls: Ext.baseCSSPrefix + 'window',
65274
65275     
65276     resizable: true,
65277
65278     
65279     draggable: true,
65280
65281     
65282     constrain: false,
65283
65284     
65285     constrainHeader: false,
65286
65287     
65288     plain: false,
65289
65290     
65291     minimizable: false,
65292
65293     
65294     maximizable: false,
65295
65296     
65297     minHeight: 100,
65298
65299     
65300     minWidth: 200,
65301
65302     
65303     expandOnShow: true,
65304
65305     
65306     collapsible: false,
65307
65308     
65309     closable: true,
65310
65311     
65312     hidden: true,
65313
65314     
65315     autoRender: true,
65316
65317     
65318     hideMode: 'visibility',
65319
65320     
65321     floating: true,
65322
65323     ariaRole: 'alertdialog',
65324
65325     itemCls: 'x-window-item',
65326
65327     overlapHeader: true,
65328
65329     ignoreHeaderBorderManagement: true,
65330
65331     
65332     initComponent: function() {
65333         var me = this;
65334         me.callParent();
65335         me.addEvents(
65336             
65337
65338             
65339
65340             
65341             'resize',
65342
65343             
65344             'maximize',
65345
65346             
65347             'minimize',
65348
65349             
65350             'restore'
65351         );
65352
65353         if (me.plain) {
65354             me.addClsWithUI('plain');
65355         }
65356
65357         if (me.modal) {
65358             me.ariaRole = 'dialog';
65359         }
65360     },
65361
65362     
65363     
65364
65365     initStateEvents: function(){
65366         var events = this.stateEvents;
65367         
65368         Ext.each(['maximize', 'restore', 'resize', 'dragend'], function(event){
65369             if (Ext.Array.indexOf(events, event)) {
65370                 events.push(event);
65371             }
65372         });
65373         this.callParent();
65374     },
65375
65376     getState: function() {
65377         var me = this,
65378             state = me.callParent() || {},
65379             maximized = !!me.maximized;
65380
65381         state.maximized = maximized;
65382         Ext.apply(state, {
65383             size: maximized ? me.restoreSize : me.getSize(),
65384             pos: maximized ? me.restorePos : me.getPosition()
65385         });
65386         return state;
65387     },
65388
65389     applyState: function(state){
65390         var me = this;
65391
65392         if (state) {
65393             me.maximized = state.maximized;
65394             if (me.maximized) {
65395                 me.hasSavedRestore = true;
65396                 me.restoreSize = state.size;
65397                 me.restorePos = state.pos;
65398             } else {
65399                 Ext.apply(me, {
65400                     width: state.size.width,
65401                     height: state.size.height,
65402                     x: state.pos[0],
65403                     y: state.pos[1]
65404                 });
65405             }
65406         }
65407     },
65408
65409     
65410     onMouseDown: function (e) {
65411         var preventFocus;
65412             
65413         if (this.floating) {
65414             if (Ext.fly(e.getTarget()).focusable()) {
65415                 preventFocus = true;
65416             }
65417             this.toFront(preventFocus);
65418         }
65419     },
65420
65421     
65422     onRender: function(ct, position) {
65423         var me = this;
65424         me.callParent(arguments);
65425         me.focusEl = me.el;
65426
65427         
65428         if (me.maximizable) {
65429             me.header.on({
65430                 dblclick: {
65431                     fn: me.toggleMaximize,
65432                     element: 'el',
65433                     scope: me
65434                 }
65435             });
65436         }
65437     },
65438
65439     
65440     afterRender: function() {
65441         var me = this,
65442             hidden = me.hidden,
65443             keyMap;
65444
65445         me.hidden = false;
65446         
65447         me.callParent();
65448         me.hidden = hidden;
65449
65450         
65451         me.proxy = me.getProxy();
65452
65453         
65454         me.mon(me.el, 'mousedown', me.onMouseDown, me);
65455         
65456         
65457         me.el.set({
65458             tabIndex: -1
65459         });
65460
65461         
65462         if (me.maximized) {
65463             me.maximized = false;
65464             me.maximize();
65465         }
65466
65467         if (me.closable) {
65468             keyMap = me.getKeyMap();
65469             keyMap.on(27, me.onEsc, me);
65470
65471             
65472                 keyMap.disable();
65473             
65474         }
65475
65476         if (!hidden) {
65477             me.syncMonitorWindowResize();
65478             me.doConstrain();
65479         }
65480     },
65481
65482     
65483     initDraggable: function() {
65484         var me = this,
65485             ddConfig;
65486
65487         if (!me.header) {
65488             me.updateHeader(true);
65489         }
65490
65491         
65492         if (me.header) {
65493             ddConfig = Ext.applyIf({
65494                 el: me.el,
65495                 delegate: '#' + me.header.id
65496             }, me.draggable);
65497
65498             
65499             if (me.constrain || me.constrainHeader) {
65500                 ddConfig.constrain = me.constrain;
65501                 ddConfig.constrainDelegate = me.constrainHeader;
65502                 ddConfig.constrainTo = me.constrainTo || me.container;
65503             }
65504
65505             
65506             me.dd = Ext.create('Ext.util.ComponentDragger', this, ddConfig);
65507             me.relayEvents(me.dd, ['dragstart', 'drag', 'dragend']);
65508         }
65509     },
65510
65511     
65512     onEsc: function(k, e) {
65513         e.stopEvent();
65514         this[this.closeAction]();
65515     },
65516
65517     
65518     beforeDestroy: function() {
65519         var me = this;
65520         if (me.rendered) {
65521             delete this.animateTarget;
65522             me.hide();
65523             Ext.destroy(
65524                 me.keyMap
65525             );
65526         }
65527         me.callParent();
65528     },
65529
65530     
65531     addTools: function() {
65532         var me = this;
65533
65534         
65535         me.callParent();
65536
65537         if (me.minimizable) {
65538             me.addTool({
65539                 type: 'minimize',
65540                 handler: Ext.Function.bind(me.minimize, me, [])
65541             });
65542         }
65543         if (me.maximizable) {
65544             me.addTool({
65545                 type: 'maximize',
65546                 handler: Ext.Function.bind(me.maximize, me, [])
65547             });
65548             me.addTool({
65549                 type: 'restore',
65550                 handler: Ext.Function.bind(me.restore, me, []),
65551                 hidden: true
65552             });
65553         }
65554     },
65555
65556     
65557     getFocusEl: function() {
65558         var me = this,
65559             f = me.focusEl,
65560             defaultComp = me.defaultButton || me.defaultFocus,
65561             t = typeof db,
65562             el,
65563             ct;
65564
65565         if (Ext.isDefined(defaultComp)) {
65566             if (Ext.isNumber(defaultComp)) {
65567                 f = me.query('button')[defaultComp];
65568             } else if (Ext.isString(defaultComp)) {
65569                 f = me.down('#' + defaultComp);
65570             } else {
65571                 f = defaultComp;
65572             }
65573         }
65574         return f || me.focusEl;
65575     },
65576
65577     
65578     beforeShow: function() {
65579         this.callParent();
65580
65581         if (this.expandOnShow) {
65582             this.expand(false);
65583         }
65584     },
65585
65586     
65587     afterShow: function(animateTarget) {
65588         var me = this,
65589             animating = animateTarget || me.animateTarget;
65590
65591
65592         
65593         
65594
65595         
65596         
65597         me.callParent(arguments);
65598
65599         if (me.maximized) {
65600             me.fitContainer();
65601         }
65602
65603         me.syncMonitorWindowResize();
65604         if (!animating) {
65605             me.doConstrain();
65606         }
65607
65608         if (me.keyMap) {
65609             me.keyMap.enable();
65610         }
65611     },
65612
65613     
65614     doClose: function() {
65615         var me = this;
65616
65617         
65618         if (me.hidden) {
65619             me.fireEvent('close', me);
65620             if (me.closeAction == 'destroy') {
65621                 this.destroy();
65622             }
65623         } else {
65624             
65625             me.hide(me.animateTarget, me.doClose, me);
65626         }
65627     },
65628
65629     
65630     afterHide: function() {
65631         var me = this;
65632
65633         
65634         me.syncMonitorWindowResize();
65635
65636         
65637         if (me.keyMap) {
65638             me.keyMap.disable();
65639         }
65640
65641         
65642         me.callParent(arguments);
65643     },
65644
65645     
65646     onWindowResize: function() {
65647         if (this.maximized) {
65648             this.fitContainer();
65649         }
65650         this.doConstrain();
65651     },
65652
65653     
65654     minimize: function() {
65655         this.fireEvent('minimize', this);
65656         return this;
65657     },
65658
65659     afterCollapse: function() {
65660         var me = this;
65661
65662         if (me.maximizable) {
65663             me.tools.maximize.hide();
65664             me.tools.restore.hide();
65665         }
65666         if (me.resizer) {
65667             me.resizer.disable();
65668         }
65669         me.callParent(arguments);
65670     },
65671
65672     afterExpand: function() {
65673         var me = this;
65674
65675         if (me.maximized) {
65676             me.tools.restore.show();
65677         } else if (me.maximizable) {
65678             me.tools.maximize.show();
65679         }
65680         if (me.resizer) {
65681             me.resizer.enable();
65682         }
65683         me.callParent(arguments);
65684     },
65685
65686     
65687     maximize: function() {
65688         var me = this;
65689
65690         if (!me.maximized) {
65691             me.expand(false);
65692             if (!me.hasSavedRestore) {
65693                 me.restoreSize = me.getSize();
65694                 me.restorePos = me.getPosition(true);
65695             }
65696             if (me.maximizable) {
65697                 me.tools.maximize.hide();
65698                 me.tools.restore.show();
65699             }
65700             me.maximized = true;
65701             me.el.disableShadow();
65702
65703             if (me.dd) {
65704                 me.dd.disable();
65705             }
65706             if (me.collapseTool) {
65707                 me.collapseTool.hide();
65708             }
65709             me.el.addCls(Ext.baseCSSPrefix + 'window-maximized');
65710             me.container.addCls(Ext.baseCSSPrefix + 'window-maximized-ct');
65711
65712             me.syncMonitorWindowResize();
65713             me.setPosition(0, 0);
65714             me.fitContainer();
65715             me.fireEvent('maximize', me);
65716         }
65717         return me;
65718     },
65719
65720     
65721     restore: function() {
65722         var me = this,
65723             tools = me.tools;
65724
65725         if (me.maximized) {
65726             delete me.hasSavedRestore;
65727             me.removeCls(Ext.baseCSSPrefix + 'window-maximized');
65728
65729             
65730             if (tools.restore) {
65731                 tools.restore.hide();
65732             }
65733             if (tools.maximize) {
65734                 tools.maximize.show();
65735             }
65736             if (me.collapseTool) {
65737                 me.collapseTool.show();
65738             }
65739
65740             
65741             me.setPosition(me.restorePos);
65742             me.setSize(me.restoreSize);
65743
65744             
65745             delete me.restorePos;
65746             delete me.restoreSize;
65747
65748             me.maximized = false;
65749
65750             me.el.enableShadow(true);
65751
65752             
65753             if (me.dd) {
65754                 me.dd.enable();
65755             }
65756
65757             me.container.removeCls(Ext.baseCSSPrefix + 'window-maximized-ct');
65758
65759             me.syncMonitorWindowResize();
65760             me.doConstrain();
65761             me.fireEvent('restore', me);
65762         }
65763         return me;
65764     },
65765
65766     
65767     syncMonitorWindowResize: function () {
65768         var me = this,
65769             currentlyMonitoring = me._monitoringResize,
65770             
65771             yes = me.monitorResize || me.constrain || me.constrainHeader || me.maximized,
65772             
65773             veto = me.hidden || me.destroying || me.isDestroyed;
65774
65775         if (yes && !veto) {
65776             
65777             if (!currentlyMonitoring) {
65778                 
65779                 Ext.EventManager.onWindowResize(me.onWindowResize, me);
65780                 me._monitoringResize = true;
65781             }
65782         } else if (currentlyMonitoring) {
65783             
65784             Ext.EventManager.removeResizeListener(me.onWindowResize, me);
65785             me._monitoringResize = false;
65786         }
65787     },
65788
65789     
65790     toggleMaximize: function() {
65791         return this[this.maximized ? 'restore': 'maximize']();
65792     }
65793
65794     
65795 });
65796
65797
65798 Ext.define('Ext.form.field.Base', {
65799     extend: 'Ext.Component',
65800     mixins: {
65801         labelable: 'Ext.form.Labelable',
65802         field: 'Ext.form.field.Field'
65803     },
65804     alias: 'widget.field',
65805     alternateClassName: ['Ext.form.Field', 'Ext.form.BaseField'],
65806     requires: ['Ext.util.DelayedTask', 'Ext.XTemplate', 'Ext.layout.component.field.Field'],
65807
65808     
65809     fieldSubTpl: [ 
65810         '<input id="{id}" type="{type}" ',
65811         '<tpl if="name">name="{name}" </tpl>',
65812         '<tpl if="size">size="{size}" </tpl>',
65813         '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
65814         'class="{fieldCls} {typeCls}" autocomplete="off" />',
65815         {
65816             compiled: true,
65817             disableFormats: true
65818         }
65819     ],
65820
65821     
65822
65823     
65824     inputType: 'text',
65825
65826     
65827
65828     
65829     invalidText : 'The value in this field is invalid',
65830
65831     
65832     fieldCls : Ext.baseCSSPrefix + 'form-field',
65833
65834     
65835
65836     
65837     focusCls : Ext.baseCSSPrefix + 'form-focus',
65838
65839     
65840     dirtyCls : Ext.baseCSSPrefix + 'form-dirty',
65841
65842     
65843     checkChangeEvents: Ext.isIE && (!document.documentMode || document.documentMode < 9) ?
65844                         ['change', 'propertychange'] :
65845                         ['change', 'input', 'textInput', 'keyup', 'dragdrop'],
65846
65847     
65848     checkChangeBuffer: 50,
65849
65850     componentLayout: 'field',
65851
65852     
65853     readOnly : false,
65854
65855     
65856     readOnlyCls: Ext.baseCSSPrefix + 'form-readonly',
65857
65858     
65859
65860     
65861     validateOnBlur: true,
65862
65863     
65864     hasFocus : false,
65865
65866     baseCls: Ext.baseCSSPrefix + 'field',
65867
65868     maskOnDisable: false,
65869
65870     
65871     initComponent : function() {
65872         var me = this;
65873
65874         me.callParent();
65875
65876         me.subTplData = me.subTplData || {};
65877
65878         me.addEvents(
65879             
65880             'focus',
65881             
65882             'blur',
65883             
65884             'specialkey'
65885         );
65886
65887         
65888         me.initLabelable();
65889         me.initField();
65890
65891         
65892         if (!me.name) {
65893             me.name = me.getInputId();
65894         }
65895     },
65896
65897     
65898     getInputId: function() {
65899         return this.inputId || (this.inputId = Ext.id());
65900     },
65901
65902     
65903     getSubTplData: function() {
65904         var me = this,
65905             type = me.inputType,
65906             inputId = me.getInputId();
65907
65908         return Ext.applyIf(me.subTplData, {
65909             id: inputId,
65910             cmpId: me.id,
65911             name: me.name || inputId,
65912             type: type,
65913             size: me.size || 20,
65914             cls: me.cls,
65915             fieldCls: me.fieldCls,
65916             tabIdx: me.tabIndex,
65917             typeCls: Ext.baseCSSPrefix + 'form-' + (type === 'password' ? 'text' : type)
65918         });
65919     },
65920
65921     afterRender: function() {
65922         this.callParent();
65923         
65924         if (this.inputEl) {
65925             this.inputEl.selectable();
65926         }
65927     },
65928
65929     
65930     getSubTplMarkup: function() {
65931         return this.getTpl('fieldSubTpl').apply(this.getSubTplData());
65932     },
65933
65934     initRenderTpl: function() {
65935         var me = this;
65936         if (!me.hasOwnProperty('renderTpl')) {
65937             me.renderTpl = me.getTpl('labelableRenderTpl');
65938         }
65939         return me.callParent();
65940     },
65941
65942     initRenderData: function() {
65943         return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
65944     },
65945
65946     
65947     setFieldStyle: function(style) {
65948         var me = this,
65949             inputEl = me.inputEl;
65950         if (inputEl) {
65951             inputEl.applyStyles(style);
65952         }
65953         me.fieldStyle = style;
65954     },
65955
65956     
65957     onRender : function() {
65958         var me = this,
65959             fieldStyle = me.fieldStyle;
65960
65961         me.onLabelableRender();
65962
65963         
65964         me.addChildEls({ name: 'inputEl', id: me.getInputId() });
65965
65966         me.callParent(arguments);
65967
65968         
65969         me.setRawValue(me.rawValue);
65970
65971         if (me.readOnly) {
65972             me.setReadOnly(true);
65973         }
65974         if (me.disabled) {
65975             me.disable();
65976         }
65977         if (fieldStyle) {
65978             me.setFieldStyle(fieldStyle);
65979         }
65980
65981         me.renderActiveError();
65982     },
65983
65984     initAria: function() {
65985         var me = this;
65986         me.callParent();
65987
65988         
65989         me.getActionEl().dom.setAttribute('aria-describedby', Ext.id(me.errorEl));
65990     },
65991
65992     getFocusEl: function() {
65993         return this.inputEl;
65994     },
65995
65996     isFileUpload: function() {
65997         return this.inputType === 'file';
65998     },
65999
66000     extractFileInput: function() {
66001         var me = this,
66002             fileInput = me.isFileUpload() ? me.inputEl.dom : null,
66003             clone;
66004         if (fileInput) {
66005             clone = fileInput.cloneNode(true);
66006             fileInput.parentNode.replaceChild(clone, fileInput);
66007             me.inputEl = Ext.get(clone);
66008         }
66009         return fileInput;
66010     },
66011
66012     
66013     getSubmitData: function() {
66014         var me = this,
66015             data = null,
66016             val;
66017         if (!me.disabled && me.submitValue && !me.isFileUpload()) {
66018             val = me.getSubmitValue();
66019             if (val !== null) {
66020                 data = {};
66021                 data[me.getName()] = val;
66022             }
66023         }
66024         return data;
66025     },
66026
66027     
66028     getSubmitValue: function() {
66029         return this.processRawValue(this.getRawValue());
66030     },
66031
66032     
66033     getRawValue: function() {
66034         var me = this,
66035             v = (me.inputEl ? me.inputEl.getValue() : Ext.value(me.rawValue, ''));
66036         me.rawValue = v;
66037         return v;
66038     },
66039
66040     
66041     setRawValue: function(value) {
66042         var me = this;
66043         value = Ext.value(value, '');
66044         me.rawValue = value;
66045
66046         
66047         if (me.inputEl) {
66048             me.inputEl.dom.value = value;
66049         }
66050         return value;
66051     },
66052
66053     
66054     valueToRaw: function(value) {
66055         return '' + Ext.value(value, '');
66056     },
66057
66058     
66059     rawToValue: function(rawValue) {
66060         return rawValue;
66061     },
66062
66063     
66064     processRawValue: function(value) {
66065         return value;
66066     },
66067
66068     
66069     getValue: function() {
66070         var me = this,
66071             val = me.rawToValue(me.processRawValue(me.getRawValue()));
66072         me.value = val;
66073         return val;
66074     },
66075
66076     
66077     setValue: function(value) {
66078         var me = this;
66079         me.setRawValue(me.valueToRaw(value));
66080         return me.mixins.field.setValue.call(me, value);
66081     },
66082
66083
66084     
66085     onDisable: function() {
66086         var me = this,
66087             inputEl = me.inputEl;
66088         me.callParent();
66089         if (inputEl) {
66090             inputEl.dom.disabled = true;
66091         }
66092     },
66093
66094     
66095     onEnable: function() {
66096         var me = this,
66097             inputEl = me.inputEl;
66098         me.callParent();
66099         if (inputEl) {
66100             inputEl.dom.disabled = false;
66101         }
66102     },
66103
66104     
66105     setReadOnly: function(readOnly) {
66106         var me = this,
66107             inputEl = me.inputEl;
66108         if (inputEl) {
66109             inputEl.dom.readOnly = readOnly;
66110             inputEl.dom.setAttribute('aria-readonly', readOnly);
66111         }
66112         me[readOnly ? 'addCls' : 'removeCls'](me.readOnlyCls);
66113         me.readOnly = readOnly;
66114     },
66115
66116     
66117     fireKey: function(e){
66118         if(e.isSpecialKey()){
66119             this.fireEvent('specialkey', this, Ext.create('Ext.EventObjectImpl', e));
66120         }
66121     },
66122
66123     
66124     initEvents : function(){
66125         var me = this,
66126             inputEl = me.inputEl,
66127             onChangeTask,
66128             onChangeEvent;
66129         if (inputEl) {
66130             me.mon(inputEl, Ext.EventManager.getKeyEvent(), me.fireKey,  me);
66131             me.mon(inputEl, 'focus', me.onFocus, me);
66132
66133             
66134             
66135             me.mon(inputEl, 'blur', me.onBlur, me, me.inEditor ? {buffer:10} : null);
66136
66137             
66138             onChangeTask = Ext.create('Ext.util.DelayedTask', me.checkChange, me);
66139             me.onChangeEvent = onChangeEvent = function() {
66140                 onChangeTask.delay(me.checkChangeBuffer);
66141             };
66142             Ext.each(me.checkChangeEvents, function(eventName) {
66143                 if (eventName === 'propertychange') {
66144                     me.usesPropertychange = true;
66145                 }
66146                 me.mon(inputEl, eventName, onChangeEvent);
66147             }, me);
66148         }
66149         me.callParent();
66150     },
66151
66152     doComponentLayout: function() {
66153         var me = this,
66154             inputEl = me.inputEl,
66155             usesPropertychange = me.usesPropertychange,
66156             ename = 'propertychange',
66157             onChangeEvent = me.onChangeEvent;
66158
66159         
66160         
66161         
66162         if (usesPropertychange) {
66163             me.mun(inputEl, ename, onChangeEvent);
66164         }
66165         me.callParent(arguments);
66166         if (usesPropertychange) {
66167             me.mon(inputEl, ename, onChangeEvent);
66168         }
66169     },
66170
66171     
66172     preFocus: Ext.emptyFn,
66173
66174     
66175     onFocus: function() {
66176         var me = this,
66177             focusCls = me.focusCls,
66178             inputEl = me.inputEl;
66179         me.preFocus();
66180         if (focusCls && inputEl) {
66181             inputEl.addCls(focusCls);
66182         }
66183         if (!me.hasFocus) {
66184             me.hasFocus = true;
66185             me.componentLayout.onFocus();
66186             me.fireEvent('focus', me);
66187         }
66188     },
66189
66190     
66191     beforeBlur : Ext.emptyFn,
66192
66193     
66194     onBlur : function(){
66195         var me = this,
66196             focusCls = me.focusCls,
66197             inputEl = me.inputEl;
66198
66199         if (me.destroying) {
66200             return;
66201         }
66202
66203         me.beforeBlur();
66204         if (focusCls && inputEl) {
66205             inputEl.removeCls(focusCls);
66206         }
66207         if (me.validateOnBlur) {
66208             me.validate();
66209         }
66210         me.hasFocus = false;
66211         me.fireEvent('blur', me);
66212         me.postBlur();
66213     },
66214
66215     
66216     postBlur : Ext.emptyFn,
66217
66218
66219     
66220     onDirtyChange: function(isDirty) {
66221         this[isDirty ? 'addCls' : 'removeCls'](this.dirtyCls);
66222     },
66223
66224
66225     
66226     isValid : function() {
66227         var me = this;
66228         return me.disabled || me.validateValue(me.processRawValue(me.getRawValue()));
66229     },
66230
66231
66232     
66233     validateValue: function(value) {
66234         var me = this,
66235             errors = me.getErrors(value),
66236             isValid = Ext.isEmpty(errors);
66237         if (!me.preventMark) {
66238             if (isValid) {
66239                 me.clearInvalid();
66240             } else {
66241                 me.markInvalid(errors);
66242             }
66243         }
66244
66245         return isValid;
66246     },
66247
66248     
66249     markInvalid : function(errors) {
66250         
66251         var me = this,
66252             oldMsg = me.getActiveError();
66253         me.setActiveErrors(Ext.Array.from(errors));
66254         if (oldMsg !== me.getActiveError()) {
66255             me.doComponentLayout();
66256         }
66257     },
66258
66259     
66260     clearInvalid : function() {
66261         
66262         var me = this,
66263             hadError = me.hasActiveError();
66264         me.unsetActiveError();
66265         if (hadError) {
66266             me.doComponentLayout();
66267         }
66268     },
66269
66270     
66271     renderActiveError: function() {
66272         var me = this,
66273             hasError = me.hasActiveError();
66274         if (me.inputEl) {
66275             
66276             me.inputEl[hasError ? 'addCls' : 'removeCls'](me.invalidCls + '-field');
66277         }
66278         me.mixins.labelable.renderActiveError.call(me);
66279     },
66280
66281
66282     getActionEl: function() {
66283         return this.inputEl || this.el;
66284     }
66285
66286 });
66287
66288
66289 Ext.define('Ext.form.field.Text', {
66290     extend:'Ext.form.field.Base',
66291     alias: 'widget.textfield',
66292     requires: ['Ext.form.field.VTypes', 'Ext.layout.component.field.Text'],
66293     alternateClassName: ['Ext.form.TextField', 'Ext.form.Text'],
66294
66295     
66296
66297     
66298
66299     
66300     size: 20,
66301
66302     
66303
66304     
66305     growMin : 30,
66306
66307     
66308     growMax : 800,
66309
66310     
66311     growAppend: 'W',
66312
66313     
66314
66315     
66316
66317     
66318
66319     
66320     allowBlank : true,
66321
66322     
66323     minLength : 0,
66324
66325     
66326     maxLength : Number.MAX_VALUE,
66327
66328     
66329
66330     
66331     minLengthText : 'The minimum length for this field is {0}',
66332
66333     
66334     maxLengthText : 'The maximum length for this field is {0}',
66335
66336     
66337
66338     
66339     blankText : 'This field is required',
66340
66341     
66342
66343     
66344
66345     
66346     regexText : '',
66347
66348     
66349
66350     
66351     emptyCls : Ext.baseCSSPrefix + 'form-empty-field',
66352
66353     ariaRole: 'textbox',
66354
66355     
66356
66357     componentLayout: 'textfield',
66358
66359     initComponent : function(){
66360         this.callParent();
66361         this.addEvents(
66362             
66363             'autosize',
66364
66365             
66366             'keydown',
66367             
66368             'keyup',
66369             
66370             'keypress'
66371         );
66372     },
66373
66374     
66375     initEvents : function(){
66376         var me = this,
66377             el = me.inputEl;
66378
66379         me.callParent();
66380         if(me.selectOnFocus || me.emptyText){
66381             me.mon(el, 'mousedown', me.onMouseDown, me);
66382         }
66383         if(me.maskRe || (me.vtype && me.disableKeyFilter !== true && (me.maskRe = Ext.form.field.VTypes[me.vtype+'Mask']))){
66384             me.mon(el, 'keypress', me.filterKeys, me);
66385         }
66386
66387         if (me.enableKeyEvents) {
66388             me.mon(el, {
66389                 scope: me,
66390                 keyup: me.onKeyUp,
66391                 keydown: me.onKeyDown,
66392                 keypress: me.onKeyPress
66393             });
66394         }
66395     },
66396
66397     
66398     isEqual: function(value1, value2) {
66399         return this.isEqualAsString(value1, value2);
66400     },
66401
66402     
66403     onChange: function() {
66404         this.callParent();
66405         this.autoSize();
66406     },
66407
66408     afterRender: function(){
66409         var me = this;
66410         if (me.enforceMaxLength) {
66411             me.inputEl.dom.maxLength = me.maxLength;
66412         }
66413         me.applyEmptyText();
66414         me.autoSize();
66415         me.callParent();
66416     },
66417
66418     onMouseDown: function(e){
66419         var me = this;
66420         if(!me.hasFocus){
66421             me.mon(me.inputEl, 'mouseup', Ext.emptyFn, me, { single: true, preventDefault: true });
66422         }
66423     },
66424
66425     
66426     processRawValue: function(value) {
66427         var me = this,
66428             stripRe = me.stripCharsRe,
66429             newValue;
66430
66431         if (stripRe) {
66432             newValue = value.replace(stripRe, '');
66433             if (newValue !== value) {
66434                 me.setRawValue(newValue);
66435                 value = newValue;
66436             }
66437         }
66438         return value;
66439     },
66440
66441     
66442     onDisable: function(){
66443         this.callParent();
66444         if (Ext.isIE) {
66445             this.inputEl.dom.unselectable = 'on';
66446         }
66447     },
66448
66449     
66450     onEnable: function(){
66451         this.callParent();
66452         if (Ext.isIE) {
66453             this.inputEl.dom.unselectable = '';
66454         }
66455     },
66456
66457     onKeyDown: function(e) {
66458         this.fireEvent('keydown', this, e);
66459     },
66460
66461     onKeyUp: function(e) {
66462         this.fireEvent('keyup', this, e);
66463     },
66464
66465     onKeyPress: function(e) {
66466         this.fireEvent('keypress', this, e);
66467     },
66468
66469     
66470     reset : function(){
66471         this.callParent();
66472         this.applyEmptyText();
66473     },
66474
66475     applyEmptyText : function(){
66476         var me = this,
66477             emptyText = me.emptyText,
66478             isEmpty;
66479
66480         if (me.rendered && emptyText) {
66481             isEmpty = me.getRawValue().length < 1 && !me.hasFocus;
66482
66483             if (Ext.supports.Placeholder) {
66484                 me.inputEl.dom.placeholder = emptyText;
66485             } else if (isEmpty) {
66486                 me.setRawValue(emptyText);
66487             }
66488
66489             
66490             
66491             if (isEmpty) {
66492                 me.inputEl.addCls(me.emptyCls);
66493             }
66494
66495             me.autoSize();
66496         }
66497     },
66498
66499     
66500     preFocus : function(){
66501         var me = this,
66502             inputEl = me.inputEl,
66503             emptyText = me.emptyText,
66504             isEmpty;
66505
66506         if (emptyText && !Ext.supports.Placeholder && inputEl.dom.value === emptyText) {
66507             me.setRawValue('');
66508             isEmpty = true;
66509             inputEl.removeCls(me.emptyCls);
66510         } else if (Ext.supports.Placeholder) {
66511             me.inputEl.removeCls(me.emptyCls);
66512         }
66513         if (me.selectOnFocus || isEmpty) {
66514             inputEl.dom.select();
66515         }
66516     },
66517
66518     onFocus: function() {
66519         var me = this;
66520         me.callParent(arguments);
66521         if (me.emptyText) {
66522             me.autoSize();
66523         }
66524     },
66525
66526     
66527     postBlur : function(){
66528         this.applyEmptyText();
66529     },
66530
66531     
66532     filterKeys : function(e){
66533         
66534         if (e.ctrlKey && !e.altKey) {
66535             return;
66536         }
66537         var key = e.getKey(),
66538             charCode = String.fromCharCode(e.getCharCode());
66539
66540         if(Ext.isGecko && (e.isNavKeyPress() || key === e.BACKSPACE || (key === e.DELETE && e.button === -1))){
66541             return;
66542         }
66543
66544         if(!Ext.isGecko && e.isSpecialKey() && !charCode){
66545             return;
66546         }
66547         if(!this.maskRe.test(charCode)){
66548             e.stopEvent();
66549         }
66550     },
66551
66552     
66553     getRawValue: function() {
66554         var me = this,
66555             v = me.callParent();
66556         if (v === me.emptyText) {
66557             v = '';
66558         }
66559         return v;
66560     },
66561
66562     
66563     setValue: function(value) {
66564         var me = this,
66565             inputEl = me.inputEl;
66566
66567         if (inputEl && me.emptyText && !Ext.isEmpty(value)) {
66568             inputEl.removeCls(me.emptyCls);
66569         }
66570
66571         me.callParent(arguments);
66572
66573         me.applyEmptyText();
66574         return me;
66575     },
66576
66577     
66578     getErrors: function(value) {
66579         var me = this,
66580             errors = me.callParent(arguments),
66581             validator = me.validator,
66582             emptyText = me.emptyText,
66583             allowBlank = me.allowBlank,
66584             vtype = me.vtype,
66585             vtypes = Ext.form.field.VTypes,
66586             regex = me.regex,
66587             format = Ext.String.format,
66588             msg;
66589
66590         value = value || me.processRawValue(me.getRawValue());
66591
66592         if (Ext.isFunction(validator)) {
66593             msg = validator.call(me, value);
66594             if (msg !== true) {
66595                 errors.push(msg);
66596             }
66597         }
66598
66599         if (value.length < 1 || value === emptyText) {
66600             if (!allowBlank) {
66601                 errors.push(me.blankText);
66602             }
66603             
66604             return errors;
66605         }
66606
66607         if (value.length < me.minLength) {
66608             errors.push(format(me.minLengthText, me.minLength));
66609         }
66610
66611         if (value.length > me.maxLength) {
66612             errors.push(format(me.maxLengthText, me.maxLength));
66613         }
66614
66615         if (vtype) {
66616             if(!vtypes[vtype](value, me)){
66617                 errors.push(me.vtypeText || vtypes[vtype +'Text']);
66618             }
66619         }
66620
66621         if (regex && !regex.test(value)) {
66622             errors.push(me.regexText || me.invalidText);
66623         }
66624
66625         return errors;
66626     },
66627
66628     
66629     selectText : function(start, end){
66630         var me = this,
66631             v = me.getRawValue(),
66632             doFocus = true,
66633             el = me.inputEl.dom,
66634             undef,
66635             range;
66636
66637         if (v.length > 0) {
66638             start = start === undef ? 0 : start;
66639             end = end === undef ? v.length : end;
66640             if (el.setSelectionRange) {
66641                 el.setSelectionRange(start, end);
66642             }
66643             else if(el.createTextRange) {
66644                 range = el.createTextRange();
66645                 range.moveStart('character', start);
66646                 range.moveEnd('character', end - v.length);
66647                 range.select();
66648             }
66649             doFocus = Ext.isGecko || Ext.isOpera;
66650         }
66651         if (doFocus) {
66652             me.focus();
66653         }
66654     },
66655
66656     
66657     autoSize: function() {
66658         var me = this,
66659             width;
66660         if (me.grow && me.rendered) {
66661             me.doComponentLayout();
66662             width = me.inputEl.getWidth();
66663             if (width !== me.lastInputWidth) {
66664                 me.fireEvent('autosize', width);
66665                 me.lastInputWidth = width;
66666             }
66667         }
66668     },
66669
66670     initAria: function() {
66671         this.callParent();
66672         this.getActionEl().dom.setAttribute('aria-required', this.allowBlank === false);
66673     },
66674
66675     
66676     getBodyNaturalWidth: function() {
66677         return Math.round(this.size * 6.5) + 20;
66678     }
66679
66680 });
66681
66682
66683 Ext.define('Ext.form.field.TextArea', {
66684     extend:'Ext.form.field.Text',
66685     alias: ['widget.textareafield', 'widget.textarea'],
66686     alternateClassName: 'Ext.form.TextArea',
66687     requires: ['Ext.XTemplate', 'Ext.layout.component.field.TextArea'],
66688
66689     fieldSubTpl: [
66690         '<textarea id="{id}" ',
66691             '<tpl if="name">name="{name}" </tpl>',
66692             '<tpl if="rows">rows="{rows}" </tpl>',
66693             '<tpl if="cols">cols="{cols}" </tpl>',
66694             '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
66695             'class="{fieldCls} {typeCls}" ',
66696             'autocomplete="off">',
66697         '</textarea>',
66698         {
66699             compiled: true,
66700             disableFormats: true
66701         }
66702     ],
66703
66704     
66705     growMin: 60,
66706
66707     
66708     growMax: 1000,
66709
66710     
66711     growAppend: '\n-',
66712
66713     
66714     cols: 20,
66715
66716     
66717     rows: 4,
66718
66719     
66720     enterIsSpecial: false,
66721
66722     
66723     preventScrollbars: false,
66724
66725     
66726     componentLayout: 'textareafield',
66727
66728     
66729     onRender: function(ct, position) {
66730         var me = this;
66731         Ext.applyIf(me.subTplData, {
66732             cols: me.cols,
66733             rows: me.rows
66734         });
66735
66736         me.callParent(arguments);
66737     },
66738
66739     
66740     afterRender: function(){
66741         var me = this;
66742
66743         me.callParent(arguments);
66744
66745         if (me.grow) {
66746             if (me.preventScrollbars) {
66747                 me.inputEl.setStyle('overflow', 'hidden');
66748             }
66749             me.inputEl.setHeight(me.growMin);
66750         }
66751     },
66752
66753     
66754     fireKey: function(e) {
66755         if (e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() !== e.ENTER || e.hasModifier()))) {
66756             this.fireEvent('specialkey', this, e);
66757         }
66758     },
66759
66760     
66761     autoSize: function() {
66762         var me = this,
66763             height;
66764
66765         if (me.grow && me.rendered) {
66766             me.doComponentLayout();
66767             height = me.inputEl.getHeight();
66768             if (height !== me.lastInputHeight) {
66769                 me.fireEvent('autosize', height);
66770                 me.lastInputHeight = height;
66771             }
66772         }
66773     },
66774
66775     
66776     initAria: function() {
66777         this.callParent(arguments);
66778         this.getActionEl().dom.setAttribute('aria-multiline', true);
66779     },
66780
66781     
66782     getBodyNaturalWidth: function() {
66783         return Math.round(this.cols * 6.5) + 20;
66784     }
66785
66786 });
66787
66788
66789
66790 Ext.define('Ext.window.MessageBox', {
66791     extend: 'Ext.window.Window',
66792
66793     requires: [
66794         'Ext.toolbar.Toolbar',
66795         'Ext.form.field.Text',
66796         'Ext.form.field.TextArea',
66797         'Ext.button.Button',
66798         'Ext.layout.container.Anchor',
66799         'Ext.layout.container.HBox',
66800         'Ext.ProgressBar'
66801     ],
66802
66803     alias: 'widget.messagebox',
66804
66805     
66806     OK : 1,
66807     
66808     YES : 2,
66809     
66810     NO : 4,
66811     
66812     CANCEL : 8,
66813     
66814     OKCANCEL : 9,
66815     
66816     YESNO : 6,
66817     
66818     YESNOCANCEL : 14,
66819     
66820     INFO : 'ext-mb-info',
66821     
66822     WARNING : 'ext-mb-warning',
66823     
66824     QUESTION : 'ext-mb-question',
66825     
66826     ERROR : 'ext-mb-error',
66827
66828     
66829     hideMode: 'offsets',
66830     closeAction: 'hide',
66831     resizable: false,
66832     title: '&#160;',
66833
66834     width: 600,
66835     height: 500,
66836     minWidth: 250,
66837     maxWidth: 600,
66838     minHeight: 110,
66839     maxHeight: 500,
66840     constrain: true,
66841
66842     cls: Ext.baseCSSPrefix + 'message-box',
66843
66844     layout: {
66845         type: 'anchor'
66846     },
66847
66848     
66849     defaultTextHeight : 75,
66850     
66851     minProgressWidth : 250,
66852     
66853     minPromptWidth: 250,
66854     
66855     buttonText: {
66856         ok: 'OK',
66857         yes: 'Yes',
66858         no: 'No',
66859         cancel: 'Cancel'
66860     },
66861
66862     buttonIds: [
66863         'ok', 'yes', 'no', 'cancel'
66864     ],
66865
66866     titleText: {
66867         confirm: 'Confirm',
66868         prompt: 'Prompt',
66869         wait: 'Loading...',
66870         alert: 'Attention'
66871     },
66872
66873     iconHeight: 35,
66874
66875     makeButton: function(btnIdx) {
66876         var btnId = this.buttonIds[btnIdx];
66877         return Ext.create('Ext.button.Button', {
66878             handler: this.btnCallback,
66879             itemId: btnId,
66880             scope: this,
66881             text: this.buttonText[btnId],
66882             minWidth: 75
66883         });
66884     },
66885
66886     btnCallback: function(btn) {
66887         var me = this,
66888             value,
66889             field;
66890
66891         if (me.cfg.prompt || me.cfg.multiline) {
66892             if (me.cfg.multiline) {
66893                 field = me.textArea;
66894             } else {
66895                 field = me.textField;
66896             }
66897             value = field.getValue();
66898             field.reset();
66899         }
66900
66901         
66902         btn.blur();
66903         me.hide();
66904         me.userCallback(btn.itemId, value, me.cfg);
66905     },
66906
66907     hide: function() {
66908         var me = this;
66909         me.dd.endDrag();
66910         me.progressBar.reset();
66911         me.removeCls(me.cfg.cls);
66912         me.callParent();
66913     },
66914
66915     initComponent: function() {
66916         var me = this,
66917             i, button;
66918
66919         me.title = '&#160;';
66920
66921         me.topContainer = Ext.create('Ext.container.Container', {
66922             anchor: '100%',
66923             style: {
66924                 padding: '10px',
66925                 overflow: 'hidden'
66926             },
66927             items: [
66928                 me.iconComponent = Ext.create('Ext.Component', {
66929                     cls: 'ext-mb-icon',
66930                     width: 50,
66931                     height: me.iconHeight,
66932                     style: {
66933                         'float': 'left'
66934                     }
66935                 }),
66936                 me.promptContainer = Ext.create('Ext.container.Container', {
66937                     layout: {
66938                         type: 'anchor'
66939                     },
66940                     items: [
66941                         me.msg = Ext.create('Ext.Component', {
66942                             autoEl: { tag: 'span' },
66943                             cls: 'ext-mb-text'
66944                         }),
66945                         me.textField = Ext.create('Ext.form.field.Text', {
66946                             anchor: '100%',
66947                             enableKeyEvents: true,
66948                             listeners: {
66949                                 keydown: me.onPromptKey,
66950                                 scope: me
66951                             }
66952                         }),
66953                         me.textArea = Ext.create('Ext.form.field.TextArea', {
66954                             anchor: '100%',
66955                             height: 75
66956                         })
66957                     ]
66958                 })
66959             ]
66960         });
66961         me.progressBar = Ext.create('Ext.ProgressBar', {
66962             anchor: '-10',
66963             style: 'margin-left:10px'
66964         });
66965
66966         me.items = [me.topContainer, me.progressBar];
66967
66968         
66969         me.msgButtons = [];
66970         for (i = 0; i < 4; i++) {
66971             button = me.makeButton(i);
66972             me.msgButtons[button.itemId] = button;
66973             me.msgButtons.push(button);
66974         }
66975         me.bottomTb = Ext.create('Ext.toolbar.Toolbar', {
66976             ui: 'footer',
66977             dock: 'bottom',
66978             layout: {
66979                 pack: 'center'
66980             },
66981             items: [
66982                 me.msgButtons[0],
66983                 me.msgButtons[1],
66984                 me.msgButtons[2],
66985                 me.msgButtons[3]
66986             ]
66987         });
66988         me.dockedItems = [me.bottomTb];
66989
66990         me.callParent();
66991     },
66992
66993     onPromptKey: function(textField, e) {
66994         var me = this,
66995             blur;
66996
66997         if (e.keyCode === Ext.EventObject.RETURN || e.keyCode === 10) {
66998             if (me.msgButtons.ok.isVisible()) {
66999                 blur = true;
67000                 me.msgButtons.ok.handler.call(me, me.msgButtons.ok);
67001             } else if (me.msgButtons.yes.isVisible()) {
67002                 me.msgButtons.yes.handler.call(me, me.msgButtons.yes);
67003                 blur = true;
67004             }
67005
67006             if (blur) {
67007                 me.textField.blur();
67008             }
67009         }
67010     },
67011
67012     reconfigure: function(cfg) {
67013         var me = this,
67014             buttons = cfg.buttons || 0,
67015             hideToolbar = true,
67016             initialWidth = me.maxWidth,
67017             i;
67018
67019         cfg = cfg || {};
67020         me.cfg = cfg;
67021         if (cfg.width) {
67022             initialWidth = cfg.width;
67023         }
67024
67025         
67026         delete me.defaultFocus;
67027
67028         
67029         me.animateTarget = cfg.animateTarget || undefined;
67030
67031         
67032         me.modal = cfg.modal !== false;
67033
67034         
67035         if (cfg.title) {
67036             me.setTitle(cfg.title||'&#160;');
67037         }
67038
67039         if (!me.rendered) {
67040             me.width = initialWidth;
67041             me.render(Ext.getBody());
67042         } else {
67043             me.setSize(initialWidth, me.maxHeight);
67044         }
67045         me.setPosition(-10000, -10000);
67046
67047         
67048         me.closable = cfg.closable && !cfg.wait;
67049         me.header.child('[type=close]').setVisible(cfg.closable !== false);
67050
67051         
67052         if (!cfg.title && !me.closable) {
67053             me.header.hide();
67054         } else {
67055             me.header.show();
67056         }
67057
67058         
67059         me.liveDrag = !cfg.proxyDrag;
67060
67061         
67062         me.userCallback = Ext.Function.bind(cfg.callback ||cfg.fn || Ext.emptyFn, cfg.scope || Ext.global);
67063
67064         
67065         me.setIcon(cfg.icon);
67066
67067         
67068         if (cfg.msg) {
67069             me.msg.update(cfg.msg);
67070             me.msg.show();
67071         } else {
67072             me.msg.hide();
67073         }
67074
67075         
67076         if (cfg.prompt || cfg.multiline) {
67077             me.multiline = cfg.multiline;
67078             if (cfg.multiline) {
67079                 me.textArea.setValue(cfg.value);
67080                 me.textArea.setHeight(cfg.defaultTextHeight || me.defaultTextHeight);
67081                 me.textArea.show();
67082                 me.textField.hide();
67083                 me.defaultFocus = me.textArea;
67084             } else {
67085                 me.textField.setValue(cfg.value);
67086                 me.textArea.hide();
67087                 me.textField.show();
67088                 me.defaultFocus = me.textField;
67089             }
67090         } else {
67091             me.textArea.hide();
67092             me.textField.hide();
67093         }
67094
67095         
67096         if (cfg.progress || cfg.wait) {
67097             me.progressBar.show();
67098             me.updateProgress(0, cfg.progressText);
67099             if(cfg.wait === true){
67100                 me.progressBar.wait(cfg.waitConfig);
67101             }
67102         } else {
67103             me.progressBar.hide();
67104         }
67105
67106         
67107         for (i = 0; i < 4; i++) {
67108             if (buttons & Math.pow(2, i)) {
67109
67110                 
67111                 if (!me.defaultFocus) {
67112                     me.defaultFocus = me.msgButtons[i];
67113                 }
67114                 me.msgButtons[i].show();
67115                 hideToolbar = false;
67116             } else {
67117                 me.msgButtons[i].hide();
67118             }
67119         }
67120
67121         
67122         if (hideToolbar) {
67123             me.bottomTb.hide();
67124         } else {
67125             me.bottomTb.show();
67126         }
67127     },
67128
67129     
67130     show: function(cfg) {
67131         var me = this;
67132
67133         me.reconfigure(cfg);
67134         me.addCls(cfg.cls);
67135         if (cfg.animateTarget) {
67136             me.doAutoSize(true);
67137             me.callParent();
67138         } else {
67139             me.callParent();
67140             me.doAutoSize(true);
67141         }
67142         return me;
67143     },
67144
67145     afterShow: function(){
67146         if (this.animateTarget) {
67147             this.center();
67148         }
67149         this.callParent(arguments);
67150     },
67151
67152     doAutoSize: function(center) {
67153         var me = this,
67154             icon = me.iconComponent,
67155             iconHeight = me.iconHeight;
67156
67157         if (!Ext.isDefined(me.frameWidth)) {
67158             me.frameWidth = me.el.getWidth() - me.body.getWidth();
67159         }
67160
67161         
67162         icon.setHeight(iconHeight);
67163
67164         
67165         me.minWidth = me.cfg.minWidth || Ext.getClass(this).prototype.minWidth;
67166
67167         
67168         
67169         me.topContainer.doLayout();
67170         if (Ext.isIE6 || Ext.isIEQuirks) {
67171             
67172             
67173             
67174             me.textField.setCalculatedSize(9);
67175             me.textArea.setCalculatedSize(9);
67176         }
67177         var width = me.cfg.width || me.msg.getWidth() + icon.getWidth() + 25, 
67178             height = (me.header.rendered ? me.header.getHeight() : 0) +
67179             Math.max(me.promptContainer.getHeight(), icon.getHeight()) +
67180             me.progressBar.getHeight() +
67181             (me.bottomTb.rendered ? me.bottomTb.getHeight() : 0) + 20 ;
67182
67183         
67184         icon.setHeight(Math.max(iconHeight, me.msg.getHeight()));
67185         me.setSize(width + me.frameWidth, height + me.frameWidth);
67186         if (center) {
67187             me.center();
67188         }
67189         return me;
67190     },
67191
67192     updateText: function(text) {
67193         this.msg.update(text);
67194         return this.doAutoSize(true);
67195     },
67196
67197     
67198     setIcon : function(icon) {
67199         var me = this;
67200         me.iconComponent.removeCls(me.iconCls);
67201         if (icon) {
67202             me.iconComponent.show();
67203             me.iconComponent.addCls(Ext.baseCSSPrefix + 'dlg-icon');
67204             me.iconComponent.addCls(me.iconCls = icon);
67205         } else {
67206             me.iconComponent.removeCls(Ext.baseCSSPrefix + 'dlg-icon');
67207             me.iconComponent.hide();
67208         }
67209         return me;
67210     },
67211
67212     
67213     updateProgress : function(value, progressText, msg){
67214         this.progressBar.updateProgress(value, progressText);
67215         if (msg){
67216             this.updateText(msg);
67217         }
67218         return this;
67219     },
67220
67221     onEsc: function() {
67222         if (this.closable !== false) {
67223             this.callParent(arguments);
67224         }
67225     },
67226
67227     
67228     confirm: function(cfg, msg, fn, scope) {
67229         if (Ext.isString(cfg)) {
67230             cfg = {
67231                 title: cfg,
67232                 icon: 'ext-mb-question',
67233                 msg: msg,
67234                 buttons: this.YESNO,
67235                 callback: fn,
67236                 scope: scope
67237             };
67238         }
67239         return this.show(cfg);
67240     },
67241
67242     
67243     prompt : function(cfg, msg, fn, scope, multiline, value){
67244         if (Ext.isString(cfg)) {
67245             cfg = {
67246                 prompt: true,
67247                 title: cfg,
67248                 minWidth: this.minPromptWidth,
67249                 msg: msg,
67250                 buttons: this.OKCANCEL,
67251                 callback: fn,
67252                 scope: scope,
67253                 multiline: multiline,
67254                 value: value
67255             };
67256         }
67257         return this.show(cfg);
67258     },
67259
67260     
67261     wait : function(cfg, title, config){
67262         if (Ext.isString(cfg)) {
67263             cfg = {
67264                 title : title,
67265                 msg : cfg,
67266                 closable: false,
67267                 wait: true,
67268                 modal: true,
67269                 minWidth: this.minProgressWidth,
67270                 waitConfig: config
67271             };
67272         }
67273         return this.show(cfg);
67274     },
67275
67276     
67277     alert: function(cfg, msg, fn, scope) {
67278         if (Ext.isString(cfg)) {
67279             cfg = {
67280                 title : cfg,
67281                 msg : msg,
67282                 buttons: this.OK,
67283                 fn: fn,
67284                 scope : scope,
67285                 minWidth: this.minWidth
67286             };
67287         }
67288         return this.show(cfg);
67289     },
67290
67291     
67292     progress : function(cfg, msg, progressText){
67293         if (Ext.isString(cfg)) {
67294             cfg = {
67295                 title: cfg,
67296                 msg: msg,
67297                 progress: true,
67298                 progressText: progressText
67299             };
67300         }
67301         return this.show(cfg);
67302     }
67303 }, function() {
67304     
67305     Ext.MessageBox = Ext.Msg = new this();
67306 });
67307
67308 Ext.define('Ext.form.Basic', {
67309     extend: 'Ext.util.Observable',
67310     alternateClassName: 'Ext.form.BasicForm',
67311     requires: ['Ext.util.MixedCollection', 'Ext.form.action.Load', 'Ext.form.action.Submit',
67312                'Ext.window.MessageBox', 'Ext.data.Errors', 'Ext.util.DelayedTask'],
67313
67314     
67315     constructor: function(owner, config) {
67316         var me = this,
67317             onItemAddOrRemove = me.onItemAddOrRemove;
67318
67319         
67320         me.owner = owner;
67321
67322         
67323         me.mon(owner, {
67324             add: onItemAddOrRemove,
67325             remove: onItemAddOrRemove,
67326             scope: me
67327         });
67328
67329         Ext.apply(me, config);
67330
67331         
67332         if (Ext.isString(me.paramOrder)) {
67333             me.paramOrder = me.paramOrder.split(/[\s,|]/);
67334         }
67335
67336         me.checkValidityTask = Ext.create('Ext.util.DelayedTask', me.checkValidity, me);
67337
67338         me.addEvents(
67339             
67340             'beforeaction',
67341             
67342             'actionfailed',
67343             
67344             'actioncomplete',
67345             
67346             'validitychange',
67347             
67348             'dirtychange'
67349         );
67350         me.callParent();
67351     },
67352
67353     
67354     initialize: function(){
67355         this.initialized = true;
67356         this.onValidityChange(!this.hasInvalidField());
67357     },
67358
67359     
67360
67361     
67362
67363     
67364
67365     
67366
67367     
67368
67369     
67370     timeout: 30,
67371
67372     
67373
67374     
67375
67376     
67377     paramsAsHash: false,
67378
67379     
67380     waitTitle: 'Please Wait...',
67381
67382     
67383     trackResetOnLoad: false,
67384
67385     
67386
67387     
67388
67389
67390     
67391     wasDirty: false,
67392
67393
67394     
67395     destroy: function() {
67396         this.clearListeners();
67397         this.checkValidityTask.cancel();
67398     },
67399
67400     
67401     onItemAddOrRemove: function(parent, child) {
67402         var me = this,
67403             isAdding = !!child.ownerCt,
67404             isContainer = child.isContainer;
67405
67406         function handleField(field) {
67407             
67408             me[isAdding ? 'mon' : 'mun'](field, {
67409                 validitychange: me.checkValidity,
67410                 dirtychange: me.checkDirty,
67411                 scope: me,
67412                 buffer: 100 
67413             });
67414             
67415             delete me._fields;
67416         }
67417
67418         if (child.isFormField) {
67419             handleField(child);
67420         } else if (isContainer) {
67421             
67422             if (child.isDestroyed) {
67423                 
67424                 
67425                 delete me._fields;
67426             } else {
67427                 Ext.Array.forEach(child.query('[isFormField]'), handleField);
67428             }
67429         }
67430
67431         
67432         delete this._boundItems;
67433
67434         
67435         
67436         if (me.initialized) {
67437             me.checkValidityTask.delay(10);
67438         }
67439     },
67440
67441     
67442     getFields: function() {
67443         var fields = this._fields;
67444         if (!fields) {
67445             fields = this._fields = Ext.create('Ext.util.MixedCollection');
67446             fields.addAll(this.owner.query('[isFormField]'));
67447         }
67448         return fields;
67449     },
67450
67451     
67452     getBoundItems: function() {
67453         var boundItems = this._boundItems;
67454         
67455         if (!boundItems || boundItems.getCount() === 0) {
67456             boundItems = this._boundItems = Ext.create('Ext.util.MixedCollection');
67457             boundItems.addAll(this.owner.query('[formBind]'));
67458         }
67459         
67460         return boundItems;
67461     },
67462
67463     
67464     hasInvalidField: function() {
67465         return !!this.getFields().findBy(function(field) {
67466             var preventMark = field.preventMark,
67467                 isValid;
67468             field.preventMark = true;
67469             isValid = field.isValid();
67470             field.preventMark = preventMark;
67471             return !isValid;
67472         });
67473     },
67474
67475     
67476     isValid: function() {
67477         var me = this,
67478             invalid;
67479         me.batchLayouts(function() {
67480             invalid = me.getFields().filterBy(function(field) {
67481                 return !field.validate();
67482             });
67483         });
67484         return invalid.length < 1;
67485     },
67486
67487     
67488     checkValidity: function() {
67489         var me = this,
67490             valid = !me.hasInvalidField();
67491         if (valid !== me.wasValid) {
67492             me.onValidityChange(valid);
67493             me.fireEvent('validitychange', me, valid);
67494             me.wasValid = valid;
67495         }
67496     },
67497
67498     
67499     onValidityChange: function(valid) {
67500         var boundItems = this.getBoundItems();
67501         if (boundItems) {
67502             boundItems.each(function(cmp) {
67503                 if (cmp.disabled === valid) {
67504                     cmp.setDisabled(!valid);
67505                 }
67506             });
67507         }
67508     },
67509
67510     
67511     isDirty: function() {
67512         return !!this.getFields().findBy(function(f) {
67513             return f.isDirty();
67514         });
67515     },
67516
67517     
67518     checkDirty: function() {
67519         var dirty = this.isDirty();
67520         if (dirty !== this.wasDirty) {
67521             this.fireEvent('dirtychange', this, dirty);
67522             this.wasDirty = dirty;
67523         }
67524     },
67525
67526     
67527     hasUpload: function() {
67528         return !!this.getFields().findBy(function(f) {
67529             return f.isFileUpload();
67530         });
67531     },
67532
67533     
67534     doAction: function(action, options) {
67535         if (Ext.isString(action)) {
67536             action = Ext.ClassManager.instantiateByAlias('formaction.' + action, Ext.apply({}, options, {form: this}));
67537         }
67538         if (this.fireEvent('beforeaction', this, action) !== false) {
67539             this.beforeAction(action);
67540             Ext.defer(action.run, 100, action);
67541         }
67542         return this;
67543     },
67544
67545     
67546     submit: function(options) {
67547         return this.doAction(this.standardSubmit ? 'standardsubmit' : this.api ? 'directsubmit' : 'submit', options);
67548     },
67549
67550     
67551     load: function(options) {
67552         return this.doAction(this.api ? 'directload' : 'load', options);
67553     },
67554
67555     
67556     updateRecord: function(record) {
67557         var fields = record.fields,
67558             values = this.getFieldValues(),
67559             name,
67560             obj = {};
67561
67562         fields.each(function(f) {
67563             name = f.name;
67564             if (name in values) {
67565                 obj[name] = values[name];
67566             }
67567         });
67568
67569         record.beginEdit();
67570         record.set(obj);
67571         record.endEdit();
67572
67573         return this;
67574     },
67575
67576     
67577     loadRecord: function(record) {
67578         this._record = record;
67579         return this.setValues(record.data);
67580     },
67581
67582     
67583     getRecord: function() {
67584         return this._record;
67585     },
67586
67587     
67588     beforeAction: function(action) {
67589         var waitMsg = action.waitMsg,
67590             maskCls = Ext.baseCSSPrefix + 'mask-loading',
67591             waitMsgTarget;
67592
67593         
67594         this.getFields().each(function(f) {
67595             if (f.isFormField && f.syncValue) {
67596                 f.syncValue();
67597             }
67598         });
67599
67600         if (waitMsg) {
67601             waitMsgTarget = this.waitMsgTarget;
67602             if (waitMsgTarget === true) {
67603                 this.owner.el.mask(waitMsg, maskCls);
67604             } else if (waitMsgTarget) {
67605                 waitMsgTarget = this.waitMsgTarget = Ext.get(waitMsgTarget);
67606                 waitMsgTarget.mask(waitMsg, maskCls);
67607             } else {
67608                 Ext.MessageBox.wait(waitMsg, action.waitTitle || this.waitTitle);
67609             }
67610         }
67611     },
67612
67613     
67614     afterAction: function(action, success) {
67615         if (action.waitMsg) {
67616             var MessageBox = Ext.MessageBox,
67617                 waitMsgTarget = this.waitMsgTarget;
67618             if (waitMsgTarget === true) {
67619                 this.owner.el.unmask();
67620             } else if (waitMsgTarget) {
67621                 waitMsgTarget.unmask();
67622             } else {
67623                 MessageBox.updateProgress(1);
67624                 MessageBox.hide();
67625             }
67626         }
67627         if (success) {
67628             if (action.reset) {
67629                 this.reset();
67630             }
67631             Ext.callback(action.success, action.scope || action, [this, action]);
67632             this.fireEvent('actioncomplete', this, action);
67633         } else {
67634             Ext.callback(action.failure, action.scope || action, [this, action]);
67635             this.fireEvent('actionfailed', this, action);
67636         }
67637     },
67638
67639
67640     
67641     findField: function(id) {
67642         return this.getFields().findBy(function(f) {
67643             return f.id === id || f.getName() === id;
67644         });
67645     },
67646
67647
67648     
67649     markInvalid: function(errors) {
67650         var me = this;
67651
67652         function mark(fieldId, msg) {
67653             var field = me.findField(fieldId);
67654             if (field) {
67655                 field.markInvalid(msg);
67656             }
67657         }
67658
67659         if (Ext.isArray(errors)) {
67660             Ext.each(errors, function(err) {
67661                 mark(err.id, err.msg);
67662             });
67663         }
67664         else if (errors instanceof Ext.data.Errors) {
67665             errors.each(function(err) {
67666                 mark(err.field, err.message);
67667             });
67668         }
67669         else {
67670             Ext.iterate(errors, mark);
67671         }
67672         return this;
67673     },
67674
67675     
67676     setValues: function(values) {
67677         var me = this;
67678
67679         function setVal(fieldId, val) {
67680             var field = me.findField(fieldId);
67681             if (field) {
67682                 field.setValue(val);
67683                 if (me.trackResetOnLoad) {
67684                     field.resetOriginalValue();
67685                 }
67686             }
67687         }
67688
67689         if (Ext.isArray(values)) {
67690             
67691             Ext.each(values, function(val) {
67692                 setVal(val.id, val.value);
67693             });
67694         } else {
67695             
67696             Ext.iterate(values, setVal);
67697         }
67698         return this;
67699     },
67700
67701     
67702     getValues: function(asString, dirtyOnly, includeEmptyText, useDataValues) {
67703         var values = {};
67704
67705         this.getFields().each(function(field) {
67706             if (!dirtyOnly || field.isDirty()) {
67707                 var data = field[useDataValues ? 'getModelData' : 'getSubmitData'](includeEmptyText);
67708                 if (Ext.isObject(data)) {
67709                     Ext.iterate(data, function(name, val) {
67710                         if (includeEmptyText && val === '') {
67711                             val = field.emptyText || '';
67712                         }
67713                         if (name in values) {
67714                             var bucket = values[name],
67715                                 isArray = Ext.isArray;
67716                             if (!isArray(bucket)) {
67717                                 bucket = values[name] = [bucket];
67718                             }
67719                             if (isArray(val)) {
67720                                 values[name] = bucket.concat(val);
67721                             } else {
67722                                 bucket.push(val);
67723                             }
67724                         } else {
67725                             values[name] = val;
67726                         }
67727                     });
67728                 }
67729             }
67730         });
67731
67732         if (asString) {
67733             values = Ext.Object.toQueryString(values);
67734         }
67735         return values;
67736     },
67737
67738     
67739     getFieldValues: function(dirtyOnly) {
67740         return this.getValues(false, dirtyOnly, false, true);
67741     },
67742
67743     
67744     clearInvalid: function() {
67745         var me = this;
67746         me.batchLayouts(function() {
67747             me.getFields().each(function(f) {
67748                 f.clearInvalid();
67749             });
67750         });
67751         return me;
67752     },
67753
67754     
67755     reset: function() {
67756         var me = this;
67757         me.batchLayouts(function() {
67758             me.getFields().each(function(f) {
67759                 f.reset();
67760             });
67761         });
67762         return me;
67763     },
67764
67765     
67766     applyToFields: function(obj) {
67767         this.getFields().each(function(f) {
67768             Ext.apply(f, obj);
67769         });
67770         return this;
67771     },
67772
67773     
67774     applyIfToFields: function(obj) {
67775         this.getFields().each(function(f) {
67776             Ext.applyIf(f, obj);
67777         });
67778         return this;
67779     },
67780
67781     
67782     batchLayouts: function(fn) {
67783         var me = this,
67784             suspended = new Ext.util.HashMap();
67785
67786         
67787         me.getFields().each(function(field) {
67788             var ownerCt = field.ownerCt;
67789             if (!suspended.contains(ownerCt)) {
67790                 suspended.add(ownerCt);
67791                 ownerCt.oldSuspendLayout = ownerCt.suspendLayout;
67792                 ownerCt.suspendLayout = true;
67793             }
67794         });
67795
67796         
67797         fn();
67798
67799         
67800         suspended.each(function(id, ct) {
67801             ct.suspendLayout = ct.oldSuspendLayout;
67802             delete ct.oldSuspendLayout;
67803         });
67804
67805         
67806         me.owner.doComponentLayout();
67807     }
67808 });
67809
67810
67811 Ext.define('Ext.form.FieldAncestor', {
67812
67813     
67814
67815
67816     
67817     initFieldAncestor: function() {
67818         var me = this,
67819             onSubtreeChange = me.onFieldAncestorSubtreeChange;
67820
67821         me.addEvents(
67822             
67823             'fieldvaliditychange',
67824
67825             
67826             'fielderrorchange'
67827         );
67828
67829         
67830         me.on('add', onSubtreeChange, me);
67831         me.on('remove', onSubtreeChange, me);
67832
67833         me.initFieldDefaults();
67834     },
67835
67836     
67837     initFieldDefaults: function() {
67838         if (!this.fieldDefaults) {
67839             this.fieldDefaults = {};
67840         }
67841     },
67842
67843     
67844     onFieldAncestorSubtreeChange: function(parent, child) {
67845         var me = this,
67846             isAdding = !!child.ownerCt;
67847
67848         function handleCmp(cmp) {
67849             var isLabelable = cmp.isFieldLabelable,
67850                 isField = cmp.isFormField;
67851             if (isLabelable || isField) {
67852                 if (isLabelable) {
67853                     me['onLabelable' + (isAdding ? 'Added' : 'Removed')](cmp);
67854                 }
67855                 if (isField) {
67856                     me['onField' + (isAdding ? 'Added' : 'Removed')](cmp);
67857                 }
67858             }
67859             else if (cmp.isContainer) {
67860                 Ext.Array.forEach(cmp.getRefItems(), handleCmp);
67861             }
67862         }
67863         handleCmp(child);
67864     },
67865
67866     
67867     onLabelableAdded: function(labelable) {
67868         var me = this;
67869
67870         
67871         me.mon(labelable, 'errorchange', me.handleFieldErrorChange, me, {buffer: 10});
67872
67873         labelable.setFieldDefaults(me.fieldDefaults);
67874     },
67875
67876     
67877     onFieldAdded: function(field) {
67878         var me = this;
67879         me.mon(field, 'validitychange', me.handleFieldValidityChange, me);
67880     },
67881
67882     
67883     onLabelableRemoved: function(labelable) {
67884         var me = this;
67885         me.mun(labelable, 'errorchange', me.handleFieldErrorChange, me);
67886     },
67887
67888     
67889     onFieldRemoved: function(field) {
67890         var me = this;
67891         me.mun(field, 'validitychange', me.handleFieldValidityChange, me);
67892     },
67893
67894     
67895     handleFieldValidityChange: function(field, isValid) {
67896         var me = this;
67897         me.fireEvent('fieldvaliditychange', me, field, isValid);
67898         me.onFieldValidityChange();
67899     },
67900
67901     
67902     handleFieldErrorChange: function(labelable, activeError) {
67903         var me = this;
67904         me.fireEvent('fielderrorchange', me, labelable, activeError);
67905         me.onFieldErrorChange();
67906     },
67907
67908     
67909     onFieldValidityChange: Ext.emptyFn,
67910
67911     
67912     onFieldErrorChange: Ext.emptyFn
67913
67914 });
67915
67916 Ext.define('Ext.layout.container.CheckboxGroup', {
67917     extend: 'Ext.layout.container.Container',
67918     alias: ['layout.checkboxgroup'],
67919
67920
67921     onLayout: function() {
67922         var numCols = this.getColCount(),
67923             shadowCt = this.getShadowCt(),
67924             owner = this.owner,
67925             items = owner.items,
67926             shadowItems = shadowCt.items,
67927             numItems = items.length,
67928             colIndex = 0,
67929             i, numRows;
67930
67931         
67932         
67933         
67934         
67935
67936         shadowItems.each(function(col) {
67937             col.items.clear();
67938         });
67939
67940         
67941         
67942         while (shadowItems.length > numCols) {
67943             shadowCt.remove(shadowItems.last());
67944         }
67945         while (shadowItems.length < numCols) {
67946             shadowCt.add({
67947                 xtype: 'container',
67948                 cls: owner.groupCls,
67949                 flex: 1
67950             });
67951         }
67952
67953         if (owner.vertical) {
67954             numRows = Math.ceil(numItems / numCols);
67955             for (i = 0; i < numItems; i++) {
67956                 if (i > 0 && i % numRows === 0) {
67957                     colIndex++;
67958                 }
67959                 shadowItems.getAt(colIndex).items.add(items.getAt(i));
67960             }
67961         } else {
67962             for (i = 0; i < numItems; i++) {
67963                 colIndex = i % numCols;
67964                 shadowItems.getAt(colIndex).items.add(items.getAt(i));
67965             }
67966         }
67967
67968         if (!shadowCt.rendered) {
67969             shadowCt.render(this.getRenderTarget());
67970         } else {
67971             
67972             
67973             shadowItems.each(function(col) {
67974                 var layout = col.getLayout();
67975                 layout.renderItems(layout.getLayoutItems(), layout.getRenderTarget());
67976             });
67977         }
67978
67979         shadowCt.doComponentLayout();
67980     },
67981
67982
67983     
67984     renderItems: Ext.emptyFn,
67985
67986
67987     
67988     getShadowCt: function() {
67989         var me = this,
67990             shadowCt = me.shadowCt,
67991             owner, items, item, columns, columnsIsArray, numCols, i;
67992
67993         if (!shadowCt) {
67994             
67995             owner = me.owner;
67996             columns = owner.columns;
67997             columnsIsArray = Ext.isArray(columns);
67998             numCols = me.getColCount();
67999             items = [];
68000             for(i = 0; i < numCols; i++) {
68001                 item = {
68002                     xtype: 'container',
68003                     cls: owner.groupCls
68004                 };
68005                 if (columnsIsArray) {
68006                     
68007                     
68008                     if (columns[i] < 1) {
68009                         item.flex = columns[i];
68010                     } else {
68011                         item.width = columns[i];
68012                     }
68013                 }
68014                 else {
68015                     
68016                     item.flex = 1;
68017                 }
68018                 items.push(item);
68019             }
68020
68021             
68022             shadowCt = me.shadowCt = Ext.createWidget('container', {
68023                 layout: 'hbox',
68024                 items: items,
68025                 ownerCt: owner
68026             });
68027         }
68028         
68029         return shadowCt;
68030     },
68031
68032
68033     
68034     getColCount: function() {
68035         var owner = this.owner,
68036             colsCfg = owner.columns;
68037         return Ext.isArray(colsCfg) ? colsCfg.length : (Ext.isNumber(colsCfg) ? colsCfg : owner.items.length);
68038     }
68039
68040 });
68041
68042
68043 Ext.define('Ext.form.FieldContainer', {
68044     extend: 'Ext.container.Container',
68045     mixins: {
68046         labelable: 'Ext.form.Labelable',
68047         fieldAncestor: 'Ext.form.FieldAncestor'
68048     },
68049     alias: 'widget.fieldcontainer',
68050
68051     componentLayout: 'field',
68052
68053     
68054     combineLabels: false,
68055
68056     
68057     labelConnector: ', ',
68058
68059     
68060     combineErrors: false,
68061
68062     maskOnDisable: false,
68063
68064     initComponent: function() {
68065         var me = this,
68066             onSubCmpAddOrRemove = me.onSubCmpAddOrRemove;
68067
68068         
68069         me.initLabelable();
68070         me.initFieldAncestor();
68071
68072         me.callParent();
68073     },
68074
68075     
68076     onLabelableAdded: function(labelable) {
68077         var me = this;
68078         me.mixins.fieldAncestor.onLabelableAdded.call(this, labelable);
68079         me.updateLabel();
68080     },
68081
68082     
68083     onLabelableRemoved: function(labelable) {
68084         var me = this;
68085         me.mixins.fieldAncestor.onLabelableRemoved.call(this, labelable);
68086         me.updateLabel();
68087     },
68088
68089     onRender: function() {
68090         var me = this;
68091
68092         me.onLabelableRender();
68093
68094         me.callParent(arguments);
68095     },
68096
68097     initRenderTpl: function() {
68098         var me = this;
68099         if (!me.hasOwnProperty('renderTpl')) {
68100             me.renderTpl = me.getTpl('labelableRenderTpl');
68101         }
68102         return me.callParent();
68103     },
68104
68105     initRenderData: function() {
68106         return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
68107     },
68108
68109     
68110     getFieldLabel: function() {
68111         var label = this.fieldLabel || '';
68112         if (!label && this.combineLabels) {
68113             label = Ext.Array.map(this.query('[isFieldLabelable]'), function(field) {
68114                 return field.getFieldLabel();
68115             }).join(this.labelConnector);
68116         }
68117         return label;
68118     },
68119
68120     
68121     updateLabel: function() {
68122         var me = this,
68123             label = me.labelEl;
68124         if (label) {
68125             label.update(me.getFieldLabel());
68126         }
68127     },
68128
68129
68130     
68131     onFieldErrorChange: function(field, activeError) {
68132         if (this.combineErrors) {
68133             var me = this,
68134                 oldError = me.getActiveError(),
68135                 invalidFields = Ext.Array.filter(me.query('[isFormField]'), function(field) {
68136                     return field.hasActiveError();
68137                 }),
68138                 newErrors = me.getCombinedErrors(invalidFields);
68139
68140             if (newErrors) {
68141                 me.setActiveErrors(newErrors);
68142             } else {
68143                 me.unsetActiveError();
68144             }
68145
68146             if (oldError !== me.getActiveError()) {
68147                 me.doComponentLayout();
68148             }
68149         }
68150     },
68151
68152     
68153     getCombinedErrors: function(invalidFields) {
68154         var forEach = Ext.Array.forEach,
68155             errors = [];
68156         forEach(invalidFields, function(field) {
68157             forEach(field.getActiveErrors(), function(error) {
68158                 var label = field.getFieldLabel();
68159                 errors.push((label ? label + ': ' : '') + error);
68160             });
68161         });
68162         return errors;
68163     },
68164
68165     getTargetEl: function() {
68166         return this.bodyEl || this.callParent();
68167     }
68168 });
68169
68170
68171 Ext.define('Ext.form.CheckboxGroup', {
68172     extend:'Ext.form.FieldContainer',
68173     mixins: {
68174         field: 'Ext.form.field.Field'
68175     },
68176     alias: 'widget.checkboxgroup',
68177     requires: ['Ext.layout.container.CheckboxGroup', 'Ext.form.field.Base'],
68178
68179     
68180
68181     
68182
68183     
68184     columns : 'auto',
68185
68186     
68187     vertical : false,
68188
68189     
68190     allowBlank : true,
68191
68192     
68193     blankText : "You must select at least one item in this group",
68194
68195     
68196     defaultType : 'checkboxfield',
68197
68198     
68199     groupCls : Ext.baseCSSPrefix + 'form-check-group',
68200
68201     
68202     fieldBodyCls: Ext.baseCSSPrefix + 'form-checkboxgroup-body',
68203
68204     
68205     layout: 'checkboxgroup',
68206
68207     initComponent: function() {
68208         var me = this;
68209         me.callParent();
68210         me.initField();
68211     },
68212
68213     
68214     initValue: function() {
68215         var me = this,
68216             valueCfg = me.value;
68217         me.originalValue = me.lastValue = valueCfg || me.getValue();
68218         if (valueCfg) {
68219             me.setValue(valueCfg);
68220         }
68221     },
68222
68223     
68224     onFieldAdded: function(field) {
68225         var me = this;
68226         if (field.isCheckbox) {
68227             me.mon(field, 'change', me.checkChange, me);
68228         }
68229         me.callParent(arguments);
68230     },
68231
68232     onFieldRemoved: function(field) {
68233         var me = this;
68234         if (field.isCheckbox) {
68235             me.mun(field, 'change', me.checkChange, me);
68236         }
68237         me.callParent(arguments);
68238     },
68239
68240     
68241     isEqual: function(value1, value2) {
68242         var toQueryString = Ext.Object.toQueryString;
68243         return toQueryString(value1) === toQueryString(value2);
68244     },
68245
68246     
68247     getErrors: function() {
68248         var errors = [];
68249         if (!this.allowBlank && Ext.isEmpty(this.getChecked())) {
68250             errors.push(this.blankText);
68251         }
68252         return errors;
68253     },
68254
68255     
68256     getBoxes: function() {
68257         return this.query('[isCheckbox]');
68258     },
68259
68260     
68261     eachBox: function(fn, scope) {
68262         Ext.Array.forEach(this.getBoxes(), fn, scope || this);
68263     },
68264
68265     
68266     getChecked: function() {
68267         return Ext.Array.filter(this.getBoxes(), function(cb) {
68268             return cb.getValue();
68269         });
68270     },
68271
68272     
68273     isDirty: function(){
68274         return Ext.Array.some(this.getBoxes(), function(cb) {
68275             return cb.isDirty();
68276         });
68277     },
68278
68279     
68280     setReadOnly: function(readOnly) {
68281         this.eachBox(function(cb) {
68282             cb.setReadOnly(readOnly);
68283         });
68284         this.readOnly = readOnly;
68285     },
68286
68287     
68288     reset: function() {
68289         var me = this,
68290             hadError = me.hasActiveError(),
68291             preventMark = me.preventMark;
68292         me.preventMark = true;
68293         me.batchChanges(function() {
68294             me.eachBox(function(cb) {
68295                 cb.reset();
68296             });
68297         });
68298         me.preventMark = preventMark;
68299         me.unsetActiveError();
68300         if (hadError) {
68301             me.doComponentLayout();
68302         }
68303     },
68304
68305     
68306     resetOriginalValue: function() {
68307         
68308         
68309         Ext.defer(function() {
68310             this.callParent();
68311         }, 1, this);
68312     },
68313
68314
68315     
68316     setValue: function(value) {
68317         var me = this;
68318         me.batchChanges(function() {
68319             me.eachBox(function(cb) {
68320                 var name = cb.getName(),
68321                     cbValue = false;
68322                 if (value && name in value) {
68323                     if (Ext.isArray(value[name])) {
68324                         cbValue = Ext.Array.contains(value[name], cb.inputValue);
68325                     } else {
68326                         
68327                         cbValue = value[name];
68328                     }
68329                 }
68330                 cb.setValue(cbValue);
68331             });
68332         });
68333         return me;
68334     },
68335
68336
68337     
68338     getValue: function() {
68339         var values = {};
68340         this.eachBox(function(cb) {
68341             var name = cb.getName(),
68342                 inputValue = cb.inputValue,
68343                 bucket;
68344             if (cb.getValue()) {
68345                 if (name in values) {
68346                     bucket = values[name];
68347                     if (!Ext.isArray(bucket)) {
68348                         bucket = values[name] = [bucket];
68349                     }
68350                     bucket.push(inputValue);
68351                 } else {
68352                     values[name] = inputValue;
68353                 }
68354             }
68355         });
68356         return values;
68357     },
68358
68359     
68360     getSubmitData: function() {
68361         return null;
68362     },
68363
68364     
68365     getModelData: function() {
68366         return null;
68367     },
68368
68369     validate: function() {
68370         var me = this,
68371             errors = me.getErrors(),
68372             isValid = Ext.isEmpty(errors),
68373             wasValid = !me.hasActiveError();
68374
68375         if (isValid) {
68376             me.unsetActiveError();
68377         } else {
68378             me.setActiveError(errors);
68379         }
68380         if (isValid !== wasValid) {
68381             me.fireEvent('validitychange', me, isValid);
68382             me.doComponentLayout();
68383         }
68384
68385         return isValid;
68386     }
68387
68388 }, function() {
68389
68390     this.borrow(Ext.form.field.Base, ['markInvalid', 'clearInvalid']);
68391
68392 });
68393
68394
68395
68396 Ext.define('Ext.form.CheckboxManager', {
68397     extend: 'Ext.util.MixedCollection',
68398     singleton: true,
68399
68400     getByName: function(name) {
68401         return this.filterBy(function(item) {
68402             return item.name == name;
68403         });
68404     },
68405
68406     getWithValue: function(name, value) {
68407         return this.filterBy(function(item) {
68408             return item.name == name && item.inputValue == value;
68409         });
68410     },
68411
68412     getChecked: function(name) {
68413         return this.filterBy(function(item) {
68414             return item.name == name && item.checked;
68415         });
68416     }
68417 });
68418
68419
68420 Ext.define('Ext.form.FieldSet', {
68421     extend: 'Ext.container.Container',
68422     alias: 'widget.fieldset',
68423     uses: ['Ext.form.field.Checkbox', 'Ext.panel.Tool', 'Ext.layout.container.Anchor', 'Ext.layout.component.FieldSet'],
68424
68425     
68426
68427     
68428
68429     
68430
68431     
68432
68433     
68434     collapsed: false,
68435
68436     
68437
68438     
68439     baseCls: Ext.baseCSSPrefix + 'fieldset',
68440
68441     
68442     layout: 'anchor',
68443
68444     componentLayout: 'fieldset',
68445
68446     
68447     ariaRole: '',
68448
68449     renderTpl: ['<div id="{id}-body" class="{baseCls}-body"></div>'],
68450
68451     maskOnDisable: false,
68452
68453     getElConfig: function(){
68454         return {tag: 'fieldset', id: this.id};
68455     },
68456
68457     initComponent: function() {
68458         var me = this,
68459             baseCls = me.baseCls;
68460
68461         me.callParent();
68462
68463         
68464         me.initLegend();
68465
68466         
68467         me.addChildEls('body');
68468
68469         if (me.collapsed) {
68470             me.addCls(baseCls + '-collapsed');
68471             me.collapse();
68472         }
68473     },
68474
68475     
68476     onRender: function(container, position) {
68477         this.callParent(arguments);
68478         
68479         this.initLegend();
68480     },
68481
68482     
68483     initLegend: function() {
68484         var me = this,
68485             legendItems,
68486             legend = me.legend;
68487
68488         
68489         if (!legend && (me.title || me.checkboxToggle || me.collapsible)) {
68490             legendItems = [];
68491
68492             
68493             if (me.checkboxToggle) {
68494                 legendItems.push(me.createCheckboxCmp());
68495             }
68496             
68497             else if (me.collapsible) {
68498                 legendItems.push(me.createToggleCmp());
68499             }
68500
68501             
68502             legendItems.push(me.createTitleCmp());
68503
68504             legend = me.legend = Ext.create('Ext.container.Container', {
68505                 baseCls: me.baseCls + '-header',
68506                 ariaRole: '',
68507                 ownerCt: this,
68508                 getElConfig: function(){
68509                     var result = {
68510                         tag: 'legend',
68511                         cls: this.baseCls
68512                     };
68513
68514                     
68515                     
68516                     
68517                     
68518                     if (!Ext.isGecko3) {
68519                         result.children = [{
68520                             cls: Ext.baseCSSPrefix + 'clear'
68521                         }];
68522                     }
68523                     return result;
68524                 },
68525                 items: legendItems
68526             });
68527         }
68528
68529         
68530         if (legend && !legend.rendered && me.rendered) {
68531             me.legend.render(me.el, me.body); 
68532         }
68533     },
68534
68535     
68536     createTitleCmp: function() {
68537         var me = this;
68538         me.titleCmp = Ext.create('Ext.Component', {
68539             html: me.title,
68540             getElConfig: function() {
68541                 return {
68542                     tag: Ext.isGecko3 ? 'span' : 'div',
68543                     cls: me.titleCmp.cls,
68544                     id: me.titleCmp.id
68545                 };
68546             },
68547             cls: me.baseCls + '-header-text'
68548         });
68549         return me.titleCmp;
68550     },
68551
68552     
68553
68554     
68555     createCheckboxCmp: function() {
68556         var me = this,
68557             suffix = '-checkbox';
68558
68559         me.checkboxCmp = Ext.create('Ext.form.field.Checkbox', {
68560             getElConfig: function() {
68561                 return {
68562                     tag: Ext.isGecko3 ? 'span' : 'div',
68563                     id: me.checkboxCmp.id,
68564                     cls: me.checkboxCmp.cls
68565                 };
68566             },
68567             name: me.checkboxName || me.id + suffix,
68568             cls: me.baseCls + '-header' + suffix,
68569             checked: !me.collapsed,
68570             listeners: {
68571                 change: me.onCheckChange,
68572                 scope: me
68573             }
68574         });
68575         return me.checkboxCmp;
68576     },
68577
68578     
68579
68580     
68581     createToggleCmp: function() {
68582         var me = this;
68583         me.toggleCmp = Ext.create('Ext.panel.Tool', {
68584             getElConfig: function() {
68585                 return {
68586                     tag: Ext.isGecko3 ? 'span' : 'div',
68587                     id: me.toggleCmp.id,
68588                     cls: me.toggleCmp.cls
68589                 };
68590             },
68591             type: 'toggle',
68592             handler: me.toggle,
68593             scope: me
68594         });
68595         return me.toggleCmp;
68596     },
68597
68598     
68599     setTitle: function(title) {
68600         var me = this;
68601         me.title = title;
68602         me.initLegend();
68603         me.titleCmp.update(title);
68604         return me;
68605     },
68606
68607     getTargetEl : function() {
68608         return this.body || this.frameBody || this.el;
68609     },
68610
68611     getContentTarget: function() {
68612         return this.body;
68613     },
68614
68615     
68616     getRefItems: function(deep) {
68617         var refItems = this.callParent(arguments),
68618             legend = this.legend;
68619
68620         
68621         if (legend) {
68622             refItems.unshift(legend);
68623             if (deep) {
68624                 refItems.unshift.apply(refItems, legend.getRefItems(true));
68625             }
68626         }
68627         return refItems;
68628     },
68629
68630     
68631     expand : function(){
68632         return this.setExpanded(true);
68633     },
68634
68635     
68636     collapse : function() {
68637         return this.setExpanded(false);
68638     },
68639
68640     
68641     setExpanded: function(expanded) {
68642         var me = this,
68643             checkboxCmp = me.checkboxCmp;
68644
68645         expanded = !!expanded;
68646
68647         if (checkboxCmp) {
68648             checkboxCmp.setValue(expanded);
68649         }
68650
68651         if (expanded) {
68652             me.removeCls(me.baseCls + '-collapsed');
68653         } else {
68654             me.addCls(me.baseCls + '-collapsed');
68655         }
68656         me.collapsed = !expanded;
68657         if (expanded) {
68658             
68659             me.getComponentLayout().childrenChanged = true;
68660         }
68661         me.doComponentLayout();
68662         return me;
68663     },
68664
68665     
68666     toggle: function() {
68667         this.setExpanded(!!this.collapsed);
68668     },
68669
68670     
68671     onCheckChange: function(cmp, checked) {
68672         this.setExpanded(checked);
68673     },
68674
68675     beforeDestroy : function() {
68676         var legend = this.legend;
68677         if (legend) {
68678             legend.destroy();
68679         }
68680         this.callParent();
68681     }
68682 });
68683
68684
68685 Ext.define('Ext.form.Label', {
68686     extend:'Ext.Component',
68687     alias: 'widget.label',
68688     requires: ['Ext.util.Format'],
68689
68690     
68691     
68692     
68693     
68694     maskOnDisable: false,
68695     getElConfig: function(){
68696         var me = this;
68697         return {
68698             tag: 'label', 
68699             id: me.id, 
68700             htmlFor: me.forId || '',
68701             html: me.text ? Ext.util.Format.htmlEncode(me.text) : (me.html || '') 
68702         };
68703     },
68704
68705     
68706     setText : function(text, encode){
68707         var me = this;
68708         
68709         encode = encode !== false;
68710         if(encode) {
68711             me.text = text;
68712             delete me.html;
68713         } else {
68714             me.html = text;
68715             delete me.text;
68716         }
68717         
68718         if(me.rendered){
68719             me.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(text) : text;
68720         }
68721         return this;
68722     }
68723 });
68724
68725
68726
68727 Ext.define('Ext.form.Panel', {
68728     extend:'Ext.panel.Panel',
68729     mixins: {
68730         fieldAncestor: 'Ext.form.FieldAncestor'
68731     },
68732     alias: 'widget.form',
68733     alternateClassName: ['Ext.FormPanel', 'Ext.form.FormPanel'],
68734     requires: ['Ext.form.Basic', 'Ext.util.TaskRunner'],
68735
68736     
68737
68738     
68739
68740     
68741     layout: 'anchor',
68742
68743     ariaRole: 'form',
68744
68745     initComponent: function() {
68746         var me = this;
68747
68748         if (me.frame) {
68749             me.border = false;
68750         }
68751
68752         me.initFieldAncestor();
68753         me.callParent();
68754
68755         me.relayEvents(me.form, [
68756             'beforeaction',
68757             'actionfailed',
68758             'actioncomplete',
68759             'validitychange',
68760             'dirtychange'
68761         ]);
68762
68763         
68764         if (me.pollForChanges) {
68765             me.startPolling(me.pollInterval || 500);
68766         }
68767     },
68768
68769     initItems: function() {
68770         
68771         var me = this;
68772
68773         me.form = me.createForm();
68774         me.callParent();
68775         me.form.initialize();
68776     },
68777
68778     
68779     createForm: function() {
68780         return Ext.create('Ext.form.Basic', this, Ext.applyIf({listeners: {}}, this.initialConfig));
68781     },
68782
68783     
68784     getForm: function() {
68785         return this.form;
68786     },
68787
68788     
68789     loadRecord: function(record) {
68790         return this.getForm().loadRecord(record);
68791     },
68792
68793     
68794     getRecord: function() {
68795         return this.getForm().getRecord();
68796     },
68797
68798     
68799     getValues: function() {
68800         return this.getForm().getValues();
68801     },
68802
68803     beforeDestroy: function() {
68804         this.stopPolling();
68805         this.form.destroy();
68806         this.callParent();
68807     },
68808
68809     
68810     load: function(options) {
68811         this.form.load(options);
68812     },
68813
68814     
68815     submit: function(options) {
68816         this.form.submit(options);
68817     },
68818
68819     
68820     disable: function(silent) {
68821         this.callParent(arguments);
68822         this.form.getFields().each(function(field) {
68823             field.disable();
68824         });
68825     },
68826
68827     
68828     enable: function(silent) {
68829         this.callParent(arguments);
68830         this.form.getFields().each(function(field) {
68831             field.enable();
68832         });
68833     },
68834
68835     
68836     startPolling: function(interval) {
68837         this.stopPolling();
68838         var task = Ext.create('Ext.util.TaskRunner', interval);
68839         task.start({
68840             interval: 0,
68841             run: this.checkChange,
68842             scope: this
68843         });
68844         this.pollTask = task;
68845     },
68846
68847     
68848     stopPolling: function() {
68849         var task = this.pollTask;
68850         if (task) {
68851             task.stopAll();
68852             delete this.pollTask;
68853         }
68854     },
68855
68856     
68857     checkChange: function() {
68858         this.form.getFields().each(function(field) {
68859             field.checkChange();
68860         });
68861     }
68862 });
68863
68864
68865 Ext.define('Ext.form.RadioGroup', {
68866     extend: 'Ext.form.CheckboxGroup',
68867     alias: 'widget.radiogroup',
68868
68869     
68870     
68871     allowBlank : true,
68872     
68873     blankText : 'You must select one item in this group',
68874
68875     
68876     defaultType : 'radiofield',
68877
68878     
68879     groupCls : Ext.baseCSSPrefix + 'form-radio-group',
68880
68881     getBoxes: function() {
68882         return this.query('[isRadio]');
68883     },
68884
68885     
68886     setValue: function(value) {
68887         var me = this;
68888         if (Ext.isObject(value)) {
68889             Ext.Object.each(value, function(name, cbValue) {
68890                 var radios = Ext.form.RadioManager.getWithValue(name, cbValue);
68891                 radios.each(function(cb) {
68892                     cb.setValue(true);
68893                 });
68894             });
68895         }
68896         return me;
68897     }
68898 });
68899
68900
68901 Ext.define('Ext.form.RadioManager', {
68902     extend: 'Ext.util.MixedCollection',
68903     singleton: true,
68904
68905     getByName: function(name) {
68906         return this.filterBy(function(item) {
68907             return item.name == name;
68908         });
68909     },
68910
68911     getWithValue: function(name, value) {
68912         return this.filterBy(function(item) {
68913             return item.name == name && item.inputValue == value;
68914         });
68915     },
68916
68917     getChecked: function(name) {
68918         return this.findBy(function(item) {
68919             return item.name == name && item.checked;
68920         });
68921     }
68922 });
68923
68924
68925 Ext.define('Ext.form.action.DirectLoad', {
68926     extend:'Ext.form.action.Load',
68927     requires: ['Ext.direct.Manager'],
68928     alternateClassName: 'Ext.form.Action.DirectLoad',
68929     alias: 'formaction.directload',
68930
68931     type: 'directload',
68932
68933     run: function() {
68934         this.form.api.load.apply(window, this.getArgs());
68935     },
68936
68937     
68938     getArgs: function() {
68939         var me = this,
68940             args = [],
68941             form = me.form,
68942             paramOrder = form.paramOrder,
68943             params = me.getParams(),
68944             i, len;
68945
68946         
68947         if (paramOrder) {
68948             for (i = 0, len = paramOrder.length; i < len; i++) {
68949                 args.push(params[paramOrder[i]]);
68950             }
68951         }
68952         
68953         else if (form.paramsAsHash) {
68954             args.push(params);
68955         }
68956
68957         
68958         args.push(me.onSuccess, me);
68959
68960         return args;
68961     },
68962
68963     
68964     
68965     
68966     processResponse: function(result) {
68967         return (this.result = result);
68968     },
68969
68970     onSuccess: function(result, trans) {
68971         if (trans.type == Ext.direct.Manager.self.exceptions.SERVER) {
68972             result = {};
68973         }
68974         this.callParent([result]);
68975     }
68976 });
68977
68978
68979
68980
68981 Ext.define('Ext.form.action.DirectSubmit', {
68982     extend:'Ext.form.action.Submit',
68983     requires: ['Ext.direct.Manager'],
68984     alternateClassName: 'Ext.form.Action.DirectSubmit',
68985     alias: 'formaction.directsubmit',
68986
68987     type: 'directsubmit',
68988
68989     doSubmit: function() {
68990         var me = this,
68991             callback = Ext.Function.bind(me.onSuccess, me),
68992             formEl = me.buildForm();
68993         me.form.api.submit(formEl, callback, me);
68994         Ext.removeNode(formEl);
68995     },
68996
68997     
68998     
68999     
69000     processResponse: function(result) {
69001         return (this.result = result);
69002     },
69003
69004     onSuccess: function(response, trans) {
69005         if (trans.type === Ext.direct.Manager.self.exceptions.SERVER) {
69006             response = {};
69007         }
69008         this.callParent([response]);
69009     }
69010 });
69011
69012
69013 Ext.define('Ext.form.action.StandardSubmit', {
69014     extend:'Ext.form.action.Submit',
69015     alias: 'formaction.standardsubmit',
69016
69017     
69018
69019     
69020     doSubmit: function() {
69021         var form = this.buildForm();
69022         form.submit();
69023         Ext.removeNode(form);
69024     }
69025
69026 });
69027
69028
69029 Ext.define('Ext.form.field.Checkbox', {
69030     extend: 'Ext.form.field.Base',
69031     alias: ['widget.checkboxfield', 'widget.checkbox'],
69032     alternateClassName: 'Ext.form.Checkbox',
69033     requires: ['Ext.XTemplate', 'Ext.form.CheckboxManager'],
69034
69035     
69036     fieldSubTpl: [
69037         '<tpl if="boxLabel && boxLabelAlign == \'before\'">',
69038             '<label id="{cmpId}-boxLabelEl" class="{boxLabelCls} {boxLabelCls}-{boxLabelAlign}" for="{id}">{boxLabel}</label>',
69039         '</tpl>',
69040         
69041         
69042         
69043         '<input type="button" id="{id}" ',
69044             '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
69045             'class="{fieldCls} {typeCls}" autocomplete="off" hidefocus="true" />',
69046         '<tpl if="boxLabel && boxLabelAlign == \'after\'">',
69047             '<label id="{cmpId}-boxLabelEl" class="{boxLabelCls} {boxLabelCls}-{boxLabelAlign}" for="{id}">{boxLabel}</label>',
69048         '</tpl>',
69049         {
69050             disableFormats: true,
69051             compiled: true
69052         }
69053     ],
69054
69055     isCheckbox: true,
69056
69057     
69058     focusCls: Ext.baseCSSPrefix + 'form-cb-focus',
69059
69060     
69061
69062     
69063     fieldBodyCls: Ext.baseCSSPrefix + 'form-cb-wrap',
69064
69065     
69066     checked: false,
69067
69068     
69069     checkedCls: Ext.baseCSSPrefix + 'form-cb-checked',
69070
69071     
69072
69073     
69074     boxLabelCls: Ext.baseCSSPrefix + 'form-cb-label',
69075
69076     
69077     boxLabelAlign: 'after',
69078
69079     
69080     inputValue: 'on',
69081
69082     
69083
69084     
69085
69086     
69087
69088     
69089     checkChangeEvents: [],
69090     inputType: 'checkbox',
69091     ariaRole: 'checkbox',
69092
69093     
69094     onRe: /^on$/i,
69095
69096     initComponent: function(){
69097         this.callParent(arguments);
69098         this.getManager().add(this);
69099     },
69100
69101     initValue: function() {
69102         var me = this,
69103             checked = !!me.checked;
69104
69105         
69106         me.originalValue = me.lastValue = checked;
69107
69108         
69109         me.setValue(checked);
69110     },
69111
69112     
69113     onRender : function(ct, position) {
69114         var me = this;
69115
69116         
69117         me.addChildEls('boxLabelEl');
69118
69119         Ext.applyIf(me.subTplData, {
69120             boxLabel: me.boxLabel,
69121             boxLabelCls: me.boxLabelCls,
69122             boxLabelAlign: me.boxLabelAlign
69123         });
69124
69125         me.callParent(arguments);
69126     },
69127
69128     initEvents: function() {
69129         var me = this;
69130         me.callParent();
69131         me.mon(me.inputEl, 'click', me.onBoxClick, me);
69132     },
69133
69134     
69135     onBoxClick: function(e) {
69136         var me = this;
69137         if (!me.disabled && !me.readOnly) {
69138             this.setValue(!this.checked);
69139         }
69140     },
69141
69142     
69143     getRawValue: function() {
69144         return this.checked;
69145     },
69146
69147     
69148     getValue: function() {
69149         return this.checked;
69150     },
69151
69152     
69153     getSubmitValue: function() {
69154         var unchecked = this.uncheckedValue,
69155             uncheckedVal = Ext.isDefined(unchecked) ? unchecked : null;
69156         return this.checked ? this.inputValue : uncheckedVal;
69157     },
69158
69159     
69160     setRawValue: function(value) {
69161         var me = this,
69162             inputEl = me.inputEl,
69163             inputValue = me.inputValue,
69164             checked = (value === true || value === 'true' || value === '1' || value === 1 ||
69165                 (((Ext.isString(value) || Ext.isNumber(value)) && inputValue) ? value == inputValue : me.onRe.test(value)));
69166
69167         if (inputEl) {
69168             inputEl.dom.setAttribute('aria-checked', checked);
69169             me[checked ? 'addCls' : 'removeCls'](me.checkedCls);
69170         }
69171
69172         me.checked = me.rawValue = checked;
69173         return checked;
69174     },
69175
69176     
69177     setValue: function(checked) {
69178         var me = this;
69179
69180         
69181         
69182         
69183         
69184         if (Ext.isArray(checked)) {
69185             me.getManager().getByName(me.name).each(function(cb) {
69186                 cb.setValue(Ext.Array.contains(checked, cb.inputValue));
69187             });
69188         } else {
69189             me.callParent(arguments);
69190         }
69191
69192         return me;
69193     },
69194
69195     
69196     valueToRaw: function(value) {
69197         
69198         return value;
69199     },
69200
69201     
69202     onChange: function(newVal, oldVal) {
69203         var me = this,
69204             handler = me.handler;
69205         if (handler) {
69206             handler.call(me.scope || me, me, newVal);
69207         }
69208         me.callParent(arguments);
69209     },
69210
69211     
69212     beforeDestroy: function(){
69213         this.callParent();
69214         this.getManager().removeAtKey(this.id);
69215     },
69216
69217     
69218     getManager: function() {
69219         return Ext.form.CheckboxManager;
69220     },
69221
69222     onEnable: function() {
69223         var me = this,
69224             inputEl = me.inputEl;
69225         me.callParent();
69226         if (inputEl) {
69227             
69228             inputEl.dom.disabled = me.readOnly;
69229         }
69230     },
69231
69232     setReadOnly: function(readOnly) {
69233         var me = this,
69234             inputEl = me.inputEl;
69235         if (inputEl) {
69236             
69237             inputEl.dom.disabled = readOnly || me.disabled;
69238         }
69239         me.readOnly = readOnly;
69240     },
69241
69242     
69243     
69244     getBodyNaturalWidth: function() {
69245         var me = this,
69246             bodyEl = me.bodyEl,
69247             ws = 'white-space',
69248             width;
69249         bodyEl.setStyle(ws, 'nowrap');
69250         width = bodyEl.getWidth();
69251         bodyEl.setStyle(ws, '');
69252         return width;
69253     }
69254
69255 });
69256
69257
69258
69259 Ext.define('Ext.layout.component.field.Trigger', {
69260
69261     
69262
69263     alias: ['layout.triggerfield'],
69264
69265     extend: 'Ext.layout.component.field.Field',
69266
69267     
69268
69269     type: 'triggerfield',
69270
69271     sizeBodyContents: function(width, height) {
69272         var me = this,
69273             owner = me.owner,
69274             inputEl = owner.inputEl,
69275             triggerWrap = owner.triggerWrap,
69276             triggerWidth = owner.getTriggerWidth();
69277
69278         
69279         
69280         if (owner.hideTrigger || owner.readOnly || triggerWidth > 0) {
69281             
69282             
69283             me.setElementSize(inputEl, Ext.isNumber(width) ? width - triggerWidth : width);
69284     
69285             
69286             triggerWrap.setWidth(triggerWidth);
69287         }
69288     }
69289 });
69290
69291 Ext.define('Ext.view.View', {
69292     extend: 'Ext.view.AbstractView',
69293     alternateClassName: 'Ext.DataView',
69294     alias: 'widget.dataview',
69295
69296     inheritableStatics: {
69297         EventMap: {
69298             mousedown: 'MouseDown',
69299             mouseup: 'MouseUp',
69300             click: 'Click',
69301             dblclick: 'DblClick',
69302             contextmenu: 'ContextMenu',
69303             mouseover: 'MouseOver',
69304             mouseout: 'MouseOut',
69305             mouseenter: 'MouseEnter',
69306             mouseleave: 'MouseLeave',
69307             keydown: 'KeyDown',
69308             focus: 'Focus'
69309         }
69310     },
69311
69312     addCmpEvents: function() {
69313         this.addEvents(
69314             
69315             'beforeitemmousedown',
69316             
69317             'beforeitemmouseup',
69318             
69319             'beforeitemmouseenter',
69320             
69321             'beforeitemmouseleave',
69322             
69323             'beforeitemclick',
69324             
69325             'beforeitemdblclick',
69326             
69327             'beforeitemcontextmenu',
69328             
69329             'beforeitemkeydown',
69330             
69331             'itemmousedown',
69332             
69333             'itemmouseup',
69334             
69335             'itemmouseenter',
69336             
69337             'itemmouseleave',
69338             
69339             'itemclick',
69340             
69341             'itemdblclick',
69342             
69343             'itemcontextmenu',
69344             
69345             'itemkeydown',
69346             
69347             'beforecontainermousedown',
69348             
69349             'beforecontainermouseup',
69350             
69351             'beforecontainermouseover',
69352             
69353             'beforecontainermouseout',
69354             
69355             'beforecontainerclick',
69356             
69357             'beforecontainerdblclick',
69358             
69359             'beforecontainercontextmenu',
69360             
69361             'beforecontainerkeydown',
69362             
69363             'containermouseup',
69364             
69365             'containermouseover',
69366             
69367             'containermouseout',
69368             
69369             'containerclick',
69370             
69371             'containerdblclick',
69372             
69373             'containercontextmenu',
69374             
69375             'containerkeydown',
69376
69377             
69378             'selectionchange',
69379             
69380             'beforeselect'
69381         );
69382     },
69383     
69384     afterRender: function(){
69385         var me = this,
69386             listeners;
69387
69388         me.callParent();
69389
69390         listeners = {
69391             scope: me,
69392             
69393             freezeEvent: true,
69394             click: me.handleEvent,
69395             mousedown: me.handleEvent,
69396             mouseup: me.handleEvent,
69397             dblclick: me.handleEvent,
69398             contextmenu: me.handleEvent,
69399             mouseover: me.handleEvent,
69400             mouseout: me.handleEvent,
69401             keydown: me.handleEvent
69402         };
69403
69404         me.mon(me.getTargetEl(), listeners);
69405
69406         if (me.store) {
69407             me.bindStore(me.store, true);
69408         }
69409     },
69410
69411     handleEvent: function(e) {
69412         if (this.processUIEvent(e) !== false) {
69413             this.processSpecialEvent(e);
69414         }
69415     },
69416
69417     
69418     processItemEvent: Ext.emptyFn,
69419     processContainerEvent: Ext.emptyFn,
69420     processSpecialEvent: Ext.emptyFn,
69421
69422     
69423     stillOverItem: function (event, overItem) {
69424         var nowOver;
69425
69426         
69427         
69428         
69429         
69430         
69431         
69432         if (overItem && typeof(overItem.offsetParent) === "object") {
69433             
69434             
69435             nowOver = (event.type == 'mouseout') ? event.getRelatedTarget() : event.getTarget();
69436             return Ext.fly(overItem).contains(nowOver);
69437         }
69438
69439         return false;
69440     },
69441
69442     processUIEvent: function(e) {
69443         var me = this,
69444             item = e.getTarget(me.getItemSelector(), me.getTargetEl()),
69445             map = this.statics().EventMap,
69446             index, record,
69447             type = e.type,
69448             overItem = me.mouseOverItem,
69449             newType;
69450
69451         if (!item) {
69452             if (type == 'mouseover' && me.stillOverItem(e, overItem)) {
69453                 item = overItem;
69454             }
69455
69456             
69457             if (type == 'keydown') {
69458                 record = me.getSelectionModel().getLastSelected();
69459                 if (record) {
69460                     item = me.getNode(record);
69461                 }
69462             }
69463         }
69464
69465         if (item) {
69466             index = me.indexOf(item);
69467             if (!record) {
69468                 record = me.getRecord(item);
69469             }
69470
69471             if (me.processItemEvent(record, item, index, e) === false) {
69472                 return false;
69473             }
69474
69475             newType = me.isNewItemEvent(item, e);
69476             if (newType === false) {
69477                 return false;
69478             }
69479
69480             if (
69481                 (me['onBeforeItem' + map[newType]](record, item, index, e) === false) ||
69482                 (me.fireEvent('beforeitem' + newType, me, record, item, index, e) === false) ||
69483                 (me['onItem' + map[newType]](record, item, index, e) === false)
69484             ) {
69485                 return false;
69486             }
69487
69488             me.fireEvent('item' + newType, me, record, item, index, e);
69489         }
69490         else {
69491             if (
69492                 (me.processContainerEvent(e) === false) ||
69493                 (me['onBeforeContainer' + map[type]](e) === false) ||
69494                 (me.fireEvent('beforecontainer' + type, me, e) === false) ||
69495                 (me['onContainer' + map[type]](e) === false)
69496             ) {
69497                 return false;
69498             }
69499
69500             me.fireEvent('container' + type, me, e);
69501         }
69502
69503         return true;
69504     },
69505
69506     isNewItemEvent: function (item, e) {
69507         var me = this,
69508             overItem = me.mouseOverItem,
69509             type = e.type;
69510
69511         switch (type) {
69512             case 'mouseover':
69513                 if (item === overItem) {
69514                     return false;
69515                 }
69516                 me.mouseOverItem = item;
69517                 return 'mouseenter';
69518
69519             case 'mouseout':
69520                 
69521                 if (me.stillOverItem(e, overItem)) {
69522                     return false;
69523                 }
69524                 me.mouseOverItem = null;
69525                 return 'mouseleave';
69526         }
69527         return type;
69528     },
69529
69530     
69531     onItemMouseEnter: function(record, item, index, e) {
69532         if (this.trackOver) {
69533             this.highlightItem(item);
69534         }
69535     },
69536
69537     
69538     onItemMouseLeave : function(record, item, index, e) {
69539         if (this.trackOver) {
69540             this.clearHighlight();
69541         }
69542     },
69543
69544     
69545     onItemMouseDown: Ext.emptyFn,
69546     onItemMouseUp: Ext.emptyFn,
69547     onItemFocus: Ext.emptyFn,
69548     onItemClick: Ext.emptyFn,
69549     onItemDblClick: Ext.emptyFn,
69550     onItemContextMenu: Ext.emptyFn,
69551     onItemKeyDown: Ext.emptyFn,
69552     onBeforeItemMouseDown: Ext.emptyFn,
69553     onBeforeItemMouseUp: Ext.emptyFn,
69554     onBeforeItemFocus: Ext.emptyFn,
69555     onBeforeItemMouseEnter: Ext.emptyFn,
69556     onBeforeItemMouseLeave: Ext.emptyFn,
69557     onBeforeItemClick: Ext.emptyFn,
69558     onBeforeItemDblClick: Ext.emptyFn,
69559     onBeforeItemContextMenu: Ext.emptyFn,
69560     onBeforeItemKeyDown: Ext.emptyFn,
69561
69562     
69563     onContainerMouseDown: Ext.emptyFn,
69564     onContainerMouseUp: Ext.emptyFn,
69565     onContainerMouseOver: Ext.emptyFn,
69566     onContainerMouseOut: Ext.emptyFn,
69567     onContainerClick: Ext.emptyFn,
69568     onContainerDblClick: Ext.emptyFn,
69569     onContainerContextMenu: Ext.emptyFn,
69570     onContainerKeyDown: Ext.emptyFn,
69571     onBeforeContainerMouseDown: Ext.emptyFn,
69572     onBeforeContainerMouseUp: Ext.emptyFn,
69573     onBeforeContainerMouseOver: Ext.emptyFn,
69574     onBeforeContainerMouseOut: Ext.emptyFn,
69575     onBeforeContainerClick: Ext.emptyFn,
69576     onBeforeContainerDblClick: Ext.emptyFn,
69577     onBeforeContainerContextMenu: Ext.emptyFn,
69578     onBeforeContainerKeyDown: Ext.emptyFn,
69579
69580     
69581     highlightItem: function(item) {
69582         var me = this;
69583         me.clearHighlight();
69584         me.highlightedItem = item;
69585         Ext.fly(item).addCls(me.overItemCls);
69586     },
69587
69588     
69589     clearHighlight: function() {
69590         var me = this,
69591             highlighted = me.highlightedItem;
69592
69593         if (highlighted) {
69594             Ext.fly(highlighted).removeCls(me.overItemCls);
69595             delete me.highlightedItem;
69596         }
69597     },
69598
69599     refresh: function() {
69600         var me = this;
69601         me.clearHighlight();
69602         me.callParent(arguments);
69603         if (!me.isFixedHeight()) {
69604             me.doComponentLayout();
69605         }
69606     }
69607 });
69608
69609 Ext.define('Ext.layout.component.BoundList', {
69610     extend: 'Ext.layout.component.Component',
69611     alias: 'layout.boundlist',
69612
69613     type: 'component',
69614
69615     beforeLayout: function() {
69616         return this.callParent(arguments) || this.owner.refreshed > 0;
69617     },
69618
69619     onLayout : function(width, height) {
69620         var me = this,
69621             owner = me.owner,
69622             floating = owner.floating,
69623             el = owner.el,
69624             xy = el.getXY(),
69625             isNumber = Ext.isNumber,
69626             minWidth, maxWidth, minHeight, maxHeight,
69627             naturalWidth, naturalHeight, constrainedWidth, constrainedHeight, undef;
69628
69629         if (floating) {
69630             
69631             el.setXY([-9999,-9999]);
69632         }
69633
69634         
69635         me.setTargetSize(width, height);
69636
69637         
69638         if (!isNumber(width)) {
69639             minWidth = owner.minWidth;
69640             maxWidth = owner.maxWidth;
69641             if (isNumber(minWidth) || isNumber(maxWidth)) {
69642                 naturalWidth = el.getWidth();
69643                 if (naturalWidth < minWidth) {
69644                     constrainedWidth = minWidth;
69645                 }
69646                 else if (naturalWidth > maxWidth) {
69647                     constrainedWidth = maxWidth;
69648                 }
69649                 if (constrainedWidth) {
69650                     me.setTargetSize(constrainedWidth);
69651                 }
69652             }
69653         }
69654         
69655         if (!isNumber(height)) {
69656             minHeight = owner.minHeight;
69657             maxHeight = owner.maxHeight;
69658             if (isNumber(minHeight) || isNumber(maxHeight)) {
69659                 naturalHeight = el.getHeight();
69660                 if (naturalHeight < minHeight) {
69661                     constrainedHeight = minHeight;
69662                 }
69663                 else if (naturalHeight > maxHeight) {
69664                     constrainedHeight = maxHeight;
69665                 }
69666                 if (constrainedHeight) {
69667                     me.setTargetSize(undef, constrainedHeight);
69668                 }
69669             }
69670         }
69671
69672         if (floating) {
69673             
69674             el.setXY(xy);
69675         }
69676     },
69677
69678     afterLayout: function() {
69679         var me = this,
69680             toolbar = me.owner.pagingToolbar;
69681         me.callParent();
69682         if (toolbar) {
69683             toolbar.doComponentLayout();
69684         }
69685     },
69686
69687     setTargetSize : function(width, height) {
69688         var me = this,
69689             owner = me.owner,
69690             listHeight = null,
69691             toolbar;
69692
69693         
69694         if (Ext.isNumber(height)) {
69695             listHeight = height - owner.el.getFrameWidth('tb');
69696             toolbar = owner.pagingToolbar;
69697             if (toolbar) {
69698                 listHeight -= toolbar.getHeight();
69699             }
69700         }
69701         me.setElementSize(owner.listEl, null, listHeight);
69702
69703         me.callParent(arguments);
69704     }
69705
69706 });
69707
69708
69709 Ext.define('Ext.toolbar.TextItem', {
69710     extend: 'Ext.toolbar.Item',
69711     requires: ['Ext.XTemplate'],
69712     alias: 'widget.tbtext',
69713     alternateClassName: 'Ext.Toolbar.TextItem',
69714
69715     
69716     text: '',
69717
69718     renderTpl: '{text}',
69719     
69720     baseCls: Ext.baseCSSPrefix + 'toolbar-text',
69721
69722     onRender : function() {
69723         Ext.apply(this.renderData, {
69724             text: this.text
69725         });
69726         this.callParent(arguments);
69727     },
69728
69729     
69730     setText : function(t) {
69731         if (this.rendered) {
69732             this.el.update(t);
69733             this.ownerCt.doLayout(); 
69734         } else {
69735             this.text = t;
69736         }
69737     }
69738 });
69739
69740 Ext.define('Ext.form.field.Trigger', {
69741     extend:'Ext.form.field.Text',
69742     alias: ['widget.triggerfield', 'widget.trigger'],
69743     requires: ['Ext.DomHelper', 'Ext.util.ClickRepeater', 'Ext.layout.component.field.Trigger'],
69744     alternateClassName: ['Ext.form.TriggerField', 'Ext.form.TwinTriggerField', 'Ext.form.Trigger'],
69745
69746     
69747     fieldSubTpl: [
69748         '<input id="{id}" type="{type}" ',
69749             '<tpl if="name">name="{name}" </tpl>',
69750             '<tpl if="size">size="{size}" </tpl>',
69751             '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
69752             'class="{fieldCls} {typeCls}" autocomplete="off" />',
69753         '<div id="{cmpId}-triggerWrap" class="{triggerWrapCls}" role="presentation">',
69754             '{triggerEl}',
69755             '<div class="{clearCls}" role="presentation"></div>',
69756         '</div>',
69757         {
69758             compiled: true,
69759             disableFormats: true
69760         }
69761     ],
69762
69763     
69764
69765     
69766     triggerBaseCls: Ext.baseCSSPrefix + 'form-trigger',
69767
69768     
69769     triggerWrapCls: Ext.baseCSSPrefix + 'form-trigger-wrap',
69770
69771     
69772     hideTrigger: false,
69773
69774     
69775     editable: true,
69776
69777     
69778     readOnly: false,
69779
69780     
69781
69782     
69783     repeatTriggerClick: false,
69784
69785
69786     
69787     autoSize: Ext.emptyFn,
69788     
69789     monitorTab: true,
69790     
69791     mimicing: false,
69792     
69793     triggerIndexRe: /trigger-index-(\d+)/,
69794
69795     componentLayout: 'triggerfield',
69796
69797     initComponent: function() {
69798         this.wrapFocusCls = this.triggerWrapCls + '-focus';
69799         this.callParent(arguments);
69800     },
69801
69802     
69803     onRender: function(ct, position) {
69804         var me = this,
69805             triggerCls,
69806             triggerBaseCls = me.triggerBaseCls,
69807             triggerWrapCls = me.triggerWrapCls,
69808             triggerConfigs = [],
69809             i;
69810
69811         
69812         
69813         
69814         
69815         if (!me.trigger1Cls) {
69816             me.trigger1Cls = me.triggerCls;
69817         }
69818
69819         
69820         for (i = 0; (triggerCls = me['trigger' + (i + 1) + 'Cls']) || i < 1; i++) {
69821             triggerConfigs.push({
69822                 cls: [Ext.baseCSSPrefix + 'trigger-index-' + i, triggerBaseCls, triggerCls].join(' '),
69823                 role: 'button'
69824             });
69825         }
69826         triggerConfigs[i - 1].cls += ' ' + triggerBaseCls + '-last';
69827
69828         
69829         me.addChildEls('triggerWrap');
69830
69831         Ext.applyIf(me.subTplData, {
69832             triggerWrapCls: triggerWrapCls,
69833             triggerEl: Ext.DomHelper.markup(triggerConfigs),
69834             clearCls: me.clearCls
69835         });
69836
69837         me.callParent(arguments);
69838
69839         
69840         me.triggerEl = Ext.select('.' + triggerBaseCls, true, me.triggerWrap.dom);
69841
69842         me.doc = Ext.getDoc();
69843         me.initTrigger();
69844     },
69845
69846     onEnable: function() {
69847         this.callParent();
69848         this.triggerWrap.unmask();
69849     },
69850     
69851     onDisable: function() {
69852         this.callParent();
69853         this.triggerWrap.mask();
69854     },
69855     
69856     afterRender: function() {
69857         this.callParent();
69858         this.updateEditState();
69859         this.triggerEl.unselectable();
69860     },
69861
69862     updateEditState: function() {
69863         var me = this,
69864             inputEl = me.inputEl,
69865             triggerWrap = me.triggerWrap,
69866             noeditCls = Ext.baseCSSPrefix + 'trigger-noedit',
69867             displayed,
69868             readOnly;
69869
69870         if (me.rendered) {
69871             if (me.readOnly) {
69872                 inputEl.addCls(noeditCls);
69873                 readOnly = true;
69874                 displayed = false;
69875             } else {
69876                 if (me.editable) {
69877                     inputEl.removeCls(noeditCls);
69878                     readOnly = false;
69879                 } else {
69880                     inputEl.addCls(noeditCls);
69881                     readOnly = true;
69882                 }
69883                 displayed = !me.hideTrigger;
69884             }
69885
69886             triggerWrap.setDisplayed(displayed);
69887             inputEl.dom.readOnly = readOnly;
69888             me.doComponentLayout();
69889         }
69890     },
69891
69892     
69893     getTriggerWidth: function() {
69894         var me = this,
69895             triggerWrap = me.triggerWrap,
69896             totalTriggerWidth = 0;
69897         if (triggerWrap && !me.hideTrigger && !me.readOnly) {
69898             me.triggerEl.each(function(trigger) {
69899                 totalTriggerWidth += trigger.getWidth();
69900             });
69901             totalTriggerWidth += me.triggerWrap.getFrameWidth('lr');
69902         }
69903         return totalTriggerWidth;
69904     },
69905
69906     setHideTrigger: function(hideTrigger) {
69907         if (hideTrigger != this.hideTrigger) {
69908             this.hideTrigger = hideTrigger;
69909             this.updateEditState();
69910         }
69911     },
69912
69913     
69914     setEditable: function(editable) {
69915         if (editable != this.editable) {
69916             this.editable = editable;
69917             this.updateEditState();
69918         }
69919     },
69920
69921     
69922     setReadOnly: function(readOnly) {
69923         if (readOnly != this.readOnly) {
69924             this.readOnly = readOnly;
69925             this.updateEditState();
69926         }
69927     },
69928
69929     
69930     initTrigger: function() {
69931         var me = this,
69932             triggerWrap = me.triggerWrap,
69933             triggerEl = me.triggerEl;
69934
69935         if (me.repeatTriggerClick) {
69936             me.triggerRepeater = Ext.create('Ext.util.ClickRepeater', triggerWrap, {
69937                 preventDefault: true,
69938                 handler: function(cr, e) {
69939                     me.onTriggerWrapClick(e);
69940                 }
69941             });
69942         } else {
69943             me.mon(me.triggerWrap, 'click', me.onTriggerWrapClick, me);
69944         }
69945
69946         triggerEl.addClsOnOver(me.triggerBaseCls + '-over');
69947         triggerEl.each(function(el, c, i) {
69948             el.addClsOnOver(me['trigger' + (i + 1) + 'Cls'] + '-over');
69949         });
69950         triggerEl.addClsOnClick(me.triggerBaseCls + '-click');
69951         triggerEl.each(function(el, c, i) {
69952             el.addClsOnClick(me['trigger' + (i + 1) + 'Cls'] + '-click');
69953         });
69954     },
69955
69956     
69957     onDestroy: function() {
69958         var me = this;
69959         Ext.destroyMembers(me, 'triggerRepeater', 'triggerWrap', 'triggerEl');
69960         delete me.doc;
69961         me.callParent();
69962     },
69963
69964     
69965     onFocus: function() {
69966         var me = this;
69967         me.callParent();
69968         if (!me.mimicing) {
69969             me.bodyEl.addCls(me.wrapFocusCls);
69970             me.mimicing = true;
69971             me.mon(me.doc, 'mousedown', me.mimicBlur, me, {
69972                 delay: 10
69973             });
69974             if (me.monitorTab) {
69975                 me.on('specialkey', me.checkTab, me);
69976             }
69977         }
69978     },
69979
69980     
69981     checkTab: function(me, e) {
69982         if (!this.ignoreMonitorTab && e.getKey() == e.TAB) {
69983             this.triggerBlur();
69984         }
69985     },
69986
69987     
69988     onBlur: Ext.emptyFn,
69989
69990     
69991     mimicBlur: function(e) {
69992         if (!this.isDestroyed && !this.bodyEl.contains(e.target) && this.validateBlur(e)) {
69993             this.triggerBlur();
69994         }
69995     },
69996
69997     
69998     triggerBlur: function() {
69999         var me = this;
70000         me.mimicing = false;
70001         me.mun(me.doc, 'mousedown', me.mimicBlur, me);
70002         if (me.monitorTab && me.inputEl) {
70003             me.un('specialkey', me.checkTab, me);
70004         }
70005         Ext.form.field.Trigger.superclass.onBlur.call(me);
70006         if (me.bodyEl) {
70007             me.bodyEl.removeCls(me.wrapFocusCls);
70008         }
70009     },
70010
70011     beforeBlur: Ext.emptyFn,
70012
70013     
70014     
70015     validateBlur: function(e) {
70016         return true;
70017     },
70018
70019     
70020     
70021     
70022     onTriggerWrapClick: function(e) {
70023         var me = this,
70024             t = e && e.getTarget('.' + Ext.baseCSSPrefix + 'form-trigger', null),
70025             match = t && t.className.match(me.triggerIndexRe),
70026             idx,
70027             triggerClickMethod;
70028
70029         if (match && !me.readOnly) {
70030             idx = parseInt(match[1], 10);
70031             triggerClickMethod = me['onTrigger' + (idx + 1) + 'Click'] || me.onTriggerClick;
70032             if (triggerClickMethod) {
70033                 triggerClickMethod.call(me, e);
70034             }
70035         }
70036     },
70037
70038     
70039     onTriggerClick: Ext.emptyFn
70040
70041     
70042     
70043     
70044 });
70045
70046
70047 Ext.define('Ext.form.field.Picker', {
70048     extend: 'Ext.form.field.Trigger',
70049     alias: 'widget.pickerfield',
70050     alternateClassName: 'Ext.form.Picker',
70051     requires: ['Ext.util.KeyNav'],
70052
70053     
70054     matchFieldWidth: true,
70055
70056     
70057     pickerAlign: 'tl-bl?',
70058
70059     
70060
70061     
70062     openCls: Ext.baseCSSPrefix + 'pickerfield-open',
70063
70064     
70065
70066     
70067     editable: true,
70068
70069
70070     initComponent: function() {
70071         this.callParent();
70072
70073         
70074         this.addEvents(
70075             
70076             'expand',
70077             
70078             'collapse',
70079             
70080             'select'
70081         );
70082     },
70083
70084
70085     initEvents: function() {
70086         var me = this;
70087         me.callParent();
70088
70089         
70090         me.keyNav = Ext.create('Ext.util.KeyNav', me.inputEl, {
70091             down: function() {
70092                 if (!me.isExpanded) {
70093                     
70094                     
70095                     me.onTriggerClick();
70096                 }
70097             },
70098             esc: me.collapse,
70099             scope: me,
70100             forceKeyDown: true
70101         });
70102
70103         
70104         if (!me.editable) {
70105             me.mon(me.inputEl, 'click', me.onTriggerClick, me);
70106         }
70107
70108         
70109         if (Ext.isGecko) {
70110             me.inputEl.dom.setAttribute('autocomplete', 'off');
70111         }
70112     },
70113
70114
70115     
70116     expand: function() {
70117         var me = this,
70118             bodyEl, picker, collapseIf;
70119
70120         if (me.rendered && !me.isExpanded && !me.isDestroyed) {
70121             bodyEl = me.bodyEl;
70122             picker = me.getPicker();
70123             collapseIf = me.collapseIf;
70124
70125             
70126             picker.show();
70127             me.isExpanded = true;
70128             me.alignPicker();
70129             bodyEl.addCls(me.openCls);
70130
70131             
70132             me.mon(Ext.getDoc(), {
70133                 mousewheel: collapseIf,
70134                 mousedown: collapseIf,
70135                 scope: me
70136             });
70137             Ext.EventManager.onWindowResize(me.alignPicker, me);
70138             me.fireEvent('expand', me);
70139             me.onExpand();
70140         }
70141     },
70142
70143     onExpand: Ext.emptyFn,
70144
70145     
70146     alignPicker: function() {
70147         var me = this,
70148             picker;
70149
70150         if (me.isExpanded) {
70151             picker = me.getPicker();
70152             if (me.matchFieldWidth) {
70153                 
70154                 picker.setSize(me.bodyEl.getWidth(), picker.store && picker.store.getCount() ? null : 0);
70155             }
70156             if (picker.isFloating()) {
70157                 me.doAlign();
70158             }
70159         }
70160     },
70161
70162     
70163     doAlign: function(){
70164         var me = this,
70165             picker = me.picker,
70166             aboveSfx = '-above',
70167             isAbove;
70168
70169         me.picker.alignTo(me.inputEl, me.pickerAlign, me.pickerOffset);
70170         
70171         
70172         isAbove = picker.el.getY() < me.inputEl.getY();
70173         me.bodyEl[isAbove ? 'addCls' : 'removeCls'](me.openCls + aboveSfx);
70174         picker[isAbove ? 'addCls' : 'removeCls'](picker.baseCls + aboveSfx);
70175     },
70176
70177     
70178     collapse: function() {
70179         if (this.isExpanded && !this.isDestroyed) {
70180             var me = this,
70181                 openCls = me.openCls,
70182                 picker = me.picker,
70183                 doc = Ext.getDoc(),
70184                 collapseIf = me.collapseIf,
70185                 aboveSfx = '-above';
70186
70187             
70188             picker.hide();
70189             me.isExpanded = false;
70190
70191             
70192             me.bodyEl.removeCls([openCls, openCls + aboveSfx]);
70193             picker.el.removeCls(picker.baseCls + aboveSfx);
70194
70195             
70196             doc.un('mousewheel', collapseIf, me);
70197             doc.un('mousedown', collapseIf, me);
70198             Ext.EventManager.removeResizeListener(me.alignPicker, me);
70199             me.fireEvent('collapse', me);
70200             me.onCollapse();
70201         }
70202     },
70203
70204     onCollapse: Ext.emptyFn,
70205
70206
70207     
70208     collapseIf: function(e) {
70209         var me = this;
70210         if (!me.isDestroyed && !e.within(me.bodyEl, false, true) && !e.within(me.picker.el, false, true)) {
70211             me.collapse();
70212         }
70213     },
70214
70215     
70216     getPicker: function() {
70217         var me = this;
70218         return me.picker || (me.picker = me.createPicker());
70219     },
70220
70221     
70222     createPicker: Ext.emptyFn,
70223
70224     
70225     onTriggerClick: function() {
70226         var me = this;
70227         if (!me.readOnly && !me.disabled) {
70228             if (me.isExpanded) {
70229                 me.collapse();
70230             } else {
70231                 me.expand();
70232             }
70233             me.inputEl.focus();
70234         }
70235     },
70236
70237     mimicBlur: function(e) {
70238         var me = this,
70239             picker = me.picker;
70240         
70241         if (!picker || !e.within(picker.el, false, true)) {
70242             me.callParent(arguments);
70243         }
70244     },
70245
70246     onDestroy : function(){
70247         var me = this,
70248             picker = me.picker;
70249
70250         Ext.EventManager.removeResizeListener(me.alignPicker, me);
70251         Ext.destroy(me.keyNav);
70252         if (picker) {
70253             delete picker.pickerField;
70254             picker.destroy();
70255         }
70256         me.callParent();
70257     }
70258
70259 });
70260
70261
70262
70263 Ext.define('Ext.form.field.Spinner', {
70264     extend: 'Ext.form.field.Trigger',
70265     alias: 'widget.spinnerfield',
70266     alternateClassName: 'Ext.form.Spinner',
70267     requires: ['Ext.util.KeyNav'],
70268
70269     trigger1Cls: Ext.baseCSSPrefix + 'form-spinner-up',
70270     trigger2Cls: Ext.baseCSSPrefix + 'form-spinner-down',
70271
70272     
70273     spinUpEnabled: true,
70274
70275     
70276     spinDownEnabled: true,
70277
70278     
70279     keyNavEnabled: true,
70280
70281     
70282     mouseWheelEnabled: true,
70283
70284     
70285     repeatTriggerClick: true,
70286
70287     
70288     onSpinUp: Ext.emptyFn,
70289
70290     
70291     onSpinDown: Ext.emptyFn,
70292
70293     initComponent: function() {
70294         this.callParent();
70295
70296         this.addEvents(
70297             
70298             'spin',
70299
70300             
70301             'spinup',
70302
70303             
70304             'spindown'
70305         );
70306     },
70307
70308     
70309     onRender: function() {
70310         var me = this,
70311             triggers;
70312
70313         me.callParent(arguments);
70314         triggers = me.triggerEl;
70315
70316         
70317         me.spinUpEl = triggers.item(0);
70318         
70319         me.spinDownEl = triggers.item(1);
70320
70321         
70322         me.setSpinUpEnabled(me.spinUpEnabled);
70323         me.setSpinDownEnabled(me.spinDownEnabled);
70324
70325         
70326         if (me.keyNavEnabled) {
70327             me.spinnerKeyNav = Ext.create('Ext.util.KeyNav', me.inputEl, {
70328                 scope: me,
70329                 up: me.spinUp,
70330                 down: me.spinDown
70331             });
70332         }
70333
70334         
70335         if (me.mouseWheelEnabled) {
70336             me.mon(me.bodyEl, 'mousewheel', me.onMouseWheel, me);
70337         }
70338     },
70339
70340     
70341     getTriggerWidth: function() {
70342         return this.hideTrigger || this.readOnly ? 0 : this.spinUpEl.getWidth() + this.triggerWrap.getFrameWidth('lr');
70343     },
70344
70345     
70346     onTrigger1Click: function() {
70347         this.spinUp();
70348     },
70349
70350     
70351     onTrigger2Click: function() {
70352         this.spinDown();
70353     },
70354
70355     
70356     spinUp: function() {
70357         var me = this;
70358         if (me.spinUpEnabled && !me.disabled) {
70359             me.fireEvent('spin', me, 'up');
70360             me.fireEvent('spinup', me);
70361             me.onSpinUp();
70362         }
70363     },
70364
70365     
70366     spinDown: function() {
70367         var me = this;
70368         if (me.spinDownEnabled && !me.disabled) {
70369             me.fireEvent('spin', me, 'down');
70370             me.fireEvent('spindown', me);
70371             me.onSpinDown();
70372         }
70373     },
70374
70375     
70376     setSpinUpEnabled: function(enabled) {
70377         var me = this,
70378             wasEnabled = me.spinUpEnabled;
70379         me.spinUpEnabled = enabled;
70380         if (wasEnabled !== enabled && me.rendered) {
70381             me.spinUpEl[enabled ? 'removeCls' : 'addCls'](me.trigger1Cls + '-disabled');
70382         }
70383     },
70384
70385     
70386     setSpinDownEnabled: function(enabled) {
70387         var me = this,
70388             wasEnabled = me.spinDownEnabled;
70389         me.spinDownEnabled = enabled;
70390         if (wasEnabled !== enabled && me.rendered) {
70391             me.spinDownEl[enabled ? 'removeCls' : 'addCls'](me.trigger2Cls + '-disabled');
70392         }
70393     },
70394
70395     
70396     onMouseWheel: function(e) {
70397         var me = this,
70398             delta;
70399         if (me.hasFocus) {
70400             delta = e.getWheelDelta();
70401             if (delta > 0) {
70402                 me.spinUp();
70403             }
70404             else if (delta < 0) {
70405                 me.spinDown();
70406             }
70407             e.stopEvent();
70408         }
70409     },
70410
70411     onDestroy: function() {
70412         Ext.destroyMembers(this, 'spinnerKeyNav', 'spinUpEl', 'spinDownEl');
70413         this.callParent();
70414     }
70415
70416 });
70417
70418 Ext.define('Ext.form.field.Number', {
70419     extend:'Ext.form.field.Spinner',
70420     alias: 'widget.numberfield',
70421     alternateClassName: ['Ext.form.NumberField', 'Ext.form.Number'],
70422
70423     
70424     
70425
70426     
70427     allowDecimals : true,
70428
70429     
70430     decimalSeparator : '.',
70431
70432     
70433     decimalPrecision : 2,
70434
70435     
70436     minValue: Number.NEGATIVE_INFINITY,
70437
70438     
70439     maxValue: Number.MAX_VALUE,
70440
70441     
70442     step: 1,
70443
70444     
70445     minText : 'The minimum value for this field is {0}',
70446
70447     
70448     maxText : 'The maximum value for this field is {0}',
70449
70450     
70451     nanText : '{0} is not a valid number',
70452
70453     
70454     negativeText : 'The value cannot be negative',
70455
70456     
70457     baseChars : '0123456789',
70458
70459     
70460     autoStripChars: false,
70461
70462     initComponent: function() {
70463         var me = this,
70464             allowed;
70465
70466         me.callParent();
70467
70468         me.setMinValue(me.minValue);
70469         me.setMaxValue(me.maxValue);
70470
70471         
70472         if (me.disableKeyFilter !== true) {
70473             allowed = me.baseChars + '';
70474             if (me.allowDecimals) {
70475                 allowed += me.decimalSeparator;
70476             }
70477             if (me.minValue < 0) {
70478                 allowed += '-';
70479             }
70480             allowed = Ext.String.escapeRegex(allowed);
70481             me.maskRe = new RegExp('[' + allowed + ']');
70482             if (me.autoStripChars) {
70483                 me.stripCharsRe = new RegExp('[^' + allowed + ']', 'gi');
70484             }
70485         }
70486     },
70487
70488     
70489     getErrors: function(value) {
70490         var me = this,
70491             errors = me.callParent(arguments),
70492             format = Ext.String.format,
70493             num;
70494
70495         value = Ext.isDefined(value) ? value : this.processRawValue(this.getRawValue());
70496
70497         if (value.length < 1) { 
70498              return errors;
70499         }
70500
70501         value = String(value).replace(me.decimalSeparator, '.');
70502
70503         if(isNaN(value)){
70504             errors.push(format(me.nanText, value));
70505         }
70506
70507         num = me.parseValue(value);
70508
70509         if (me.minValue === 0 && num < 0) {
70510             errors.push(this.negativeText);
70511         }
70512         else if (num < me.minValue) {
70513             errors.push(format(me.minText, me.minValue));
70514         }
70515
70516         if (num > me.maxValue) {
70517             errors.push(format(me.maxText, me.maxValue));
70518         }
70519
70520
70521         return errors;
70522     },
70523
70524     rawToValue: function(rawValue) {
70525         var value = this.fixPrecision(this.parseValue(rawValue));
70526         if (value === null) {
70527             value = rawValue || null;
70528         }
70529         return  value;
70530     },
70531
70532     valueToRaw: function(value) {
70533         var me = this,
70534             decimalSeparator = me.decimalSeparator;
70535         value = me.parseValue(value);
70536         value = me.fixPrecision(value);
70537         value = Ext.isNumber(value) ? value : parseFloat(String(value).replace(decimalSeparator, '.'));
70538         value = isNaN(value) ? '' : String(value).replace('.', decimalSeparator);
70539         return value;
70540     },
70541
70542     onChange: function() {
70543         var me = this,
70544             value = me.getValue(),
70545             valueIsNull = value === null;
70546
70547         me.callParent(arguments);
70548
70549         
70550         me.setSpinUpEnabled(valueIsNull || value < me.maxValue);
70551         me.setSpinDownEnabled(valueIsNull || value > me.minValue);
70552     },
70553
70554     
70555     setMinValue : function(value) {
70556         this.minValue = Ext.Number.from(value, Number.NEGATIVE_INFINITY);
70557     },
70558
70559     
70560     setMaxValue: function(value) {
70561         this.maxValue = Ext.Number.from(value, Number.MAX_VALUE);
70562     },
70563
70564     
70565     parseValue : function(value) {
70566         value = parseFloat(String(value).replace(this.decimalSeparator, '.'));
70567         return isNaN(value) ? null : value;
70568     },
70569
70570     
70571     fixPrecision : function(value) {
70572         var me = this,
70573             nan = isNaN(value),
70574             precision = me.decimalPrecision;
70575
70576         if (nan || !value) {
70577             return nan ? '' : value;
70578         } else if (!me.allowDecimals || precision <= 0) {
70579             precision = 0;
70580         }
70581
70582         return parseFloat(Ext.Number.toFixed(parseFloat(value), precision));
70583     },
70584
70585     beforeBlur : function() {
70586         var me = this,
70587             v = me.parseValue(me.getRawValue());
70588
70589         if (!Ext.isEmpty(v)) {
70590             me.setValue(v);
70591         }
70592     },
70593
70594     onSpinUp: function() {
70595         var me = this;
70596         if (!me.readOnly) {
70597             me.setValue(Ext.Number.constrain(me.getValue() + me.step, me.minValue, me.maxValue));
70598         }
70599     },
70600
70601     onSpinDown: function() {
70602         var me = this;
70603         if (!me.readOnly) {
70604             me.setValue(Ext.Number.constrain(me.getValue() - me.step, me.minValue, me.maxValue));
70605         }
70606     }
70607 });
70608
70609
70610 Ext.define('Ext.toolbar.Paging', {
70611     extend: 'Ext.toolbar.Toolbar',
70612     alias: 'widget.pagingtoolbar',
70613     alternateClassName: 'Ext.PagingToolbar',
70614     requires: ['Ext.toolbar.TextItem', 'Ext.form.field.Number'],
70615     
70616
70617     
70618     displayInfo: false,
70619
70620     
70621     prependButtons: false,
70622
70623     
70624     displayMsg : 'Displaying {0} - {1} of {2}',
70625
70626     
70627     emptyMsg : 'No data to display',
70628
70629     
70630     beforePageText : 'Page',
70631
70632     
70633     afterPageText : 'of {0}',
70634
70635     
70636     firstText : 'First Page',
70637
70638     
70639     prevText : 'Previous Page',
70640
70641     
70642     nextText : 'Next Page',
70643
70644     
70645     lastText : 'Last Page',
70646
70647     
70648     refreshText : 'Refresh',
70649
70650     
70651     inputItemWidth : 30,
70652
70653     
70654     getPagingItems: function() {
70655         var me = this;
70656
70657         return [{
70658             itemId: 'first',
70659             tooltip: me.firstText,
70660             overflowText: me.firstText,
70661             iconCls: Ext.baseCSSPrefix + 'tbar-page-first',
70662             disabled: true,
70663             handler: me.moveFirst,
70664             scope: me
70665         },{
70666             itemId: 'prev',
70667             tooltip: me.prevText,
70668             overflowText: me.prevText,
70669             iconCls: Ext.baseCSSPrefix + 'tbar-page-prev',
70670             disabled: true,
70671             handler: me.movePrevious,
70672             scope: me
70673         },
70674         '-',
70675         me.beforePageText,
70676         {
70677             xtype: 'numberfield',
70678             itemId: 'inputItem',
70679             name: 'inputItem',
70680             cls: Ext.baseCSSPrefix + 'tbar-page-number',
70681             allowDecimals: false,
70682             minValue: 1,
70683             hideTrigger: true,
70684             enableKeyEvents: true,
70685             selectOnFocus: true,
70686             submitValue: false,
70687             width: me.inputItemWidth,
70688             margins: '-1 2 3 2',
70689             listeners: {
70690                 scope: me,
70691                 keydown: me.onPagingKeyDown,
70692                 blur: me.onPagingBlur
70693             }
70694         },{
70695             xtype: 'tbtext',
70696             itemId: 'afterTextItem',
70697             text: Ext.String.format(me.afterPageText, 1)
70698         },
70699         '-',
70700         {
70701             itemId: 'next',
70702             tooltip: me.nextText,
70703             overflowText: me.nextText,
70704             iconCls: Ext.baseCSSPrefix + 'tbar-page-next',
70705             disabled: true,
70706             handler: me.moveNext,
70707             scope: me
70708         },{
70709             itemId: 'last',
70710             tooltip: me.lastText,
70711             overflowText: me.lastText,
70712             iconCls: Ext.baseCSSPrefix + 'tbar-page-last',
70713             disabled: true,
70714             handler: me.moveLast,
70715             scope: me
70716         },
70717         '-',
70718         {
70719             itemId: 'refresh',
70720             tooltip: me.refreshText,
70721             overflowText: me.refreshText,
70722             iconCls: Ext.baseCSSPrefix + 'tbar-loading',
70723             handler: me.doRefresh,
70724             scope: me
70725         }];
70726     },
70727
70728     initComponent : function(){
70729         var me = this,
70730             pagingItems = me.getPagingItems(),
70731             userItems   = me.items || me.buttons || [];
70732
70733         if (me.prependButtons) {
70734             me.items = userItems.concat(pagingItems);
70735         } else {
70736             me.items = pagingItems.concat(userItems);
70737         }
70738         delete me.buttons;
70739
70740         if (me.displayInfo) {
70741             me.items.push('->');
70742             me.items.push({xtype: 'tbtext', itemId: 'displayItem'});
70743         }
70744
70745         me.callParent();
70746
70747         me.addEvents(
70748             
70749             'change',
70750
70751             
70752             'beforechange'
70753         );
70754         me.on('afterlayout', me.onLoad, me, {single: true});
70755
70756         me.bindStore(me.store || 'ext-empty-store', true);
70757     },
70758     
70759     updateInfo : function(){
70760         var me = this,
70761             displayItem = me.child('#displayItem'),
70762             store = me.store,
70763             pageData = me.getPageData(),
70764             count, msg;
70765
70766         if (displayItem) {
70767             count = store.getCount();
70768             if (count === 0) {
70769                 msg = me.emptyMsg;
70770             } else {
70771                 msg = Ext.String.format(
70772                     me.displayMsg,
70773                     pageData.fromRecord,
70774                     pageData.toRecord,
70775                     pageData.total
70776                 );
70777             }
70778             displayItem.setText(msg);
70779             me.doComponentLayout();
70780         }
70781     },
70782
70783     
70784     onLoad : function(){
70785         var me = this,
70786             pageData,
70787             currPage,
70788             pageCount,
70789             afterText;
70790
70791         if (!me.rendered) {
70792             return;
70793         }
70794
70795         pageData = me.getPageData();
70796         currPage = pageData.currentPage;
70797         pageCount = pageData.pageCount;
70798         afterText = Ext.String.format(me.afterPageText, isNaN(pageCount) ? 1 : pageCount);
70799
70800         me.child('#afterTextItem').setText(afterText);
70801         me.child('#inputItem').setValue(currPage);
70802         me.child('#first').setDisabled(currPage === 1);
70803         me.child('#prev').setDisabled(currPage === 1);
70804         me.child('#next').setDisabled(currPage === pageCount);
70805         me.child('#last').setDisabled(currPage === pageCount);
70806         me.child('#refresh').enable();
70807         me.updateInfo();
70808         me.fireEvent('change', me, pageData);
70809     },
70810
70811     
70812     getPageData : function(){
70813         var store = this.store,
70814             totalCount = store.getTotalCount();
70815
70816         return {
70817             total : totalCount,
70818             currentPage : store.currentPage,
70819             pageCount: Math.ceil(totalCount / store.pageSize),
70820             fromRecord: ((store.currentPage - 1) * store.pageSize) + 1,
70821             toRecord: Math.min(store.currentPage * store.pageSize, totalCount)
70822
70823         };
70824     },
70825
70826     
70827     onLoadError : function(){
70828         if (!this.rendered) {
70829             return;
70830         }
70831         this.child('#refresh').enable();
70832     },
70833
70834     
70835     readPageFromInput : function(pageData){
70836         var v = this.child('#inputItem').getValue(),
70837             pageNum = parseInt(v, 10);
70838
70839         if (!v || isNaN(pageNum)) {
70840             this.child('#inputItem').setValue(pageData.currentPage);
70841             return false;
70842         }
70843         return pageNum;
70844     },
70845
70846     onPagingFocus : function(){
70847         this.child('#inputItem').select();
70848     },
70849
70850     
70851     onPagingBlur : function(e){
70852         var curPage = this.getPageData().currentPage;
70853         this.child('#inputItem').setValue(curPage);
70854     },
70855
70856     
70857     onPagingKeyDown : function(field, e){
70858         var me = this,
70859             k = e.getKey(),
70860             pageData = me.getPageData(),
70861             increment = e.shiftKey ? 10 : 1,
70862             pageNum;
70863
70864         if (k == e.RETURN) {
70865             e.stopEvent();
70866             pageNum = me.readPageFromInput(pageData);
70867             if (pageNum !== false) {
70868                 pageNum = Math.min(Math.max(1, pageNum), pageData.pageCount);
70869                 if(me.fireEvent('beforechange', me, pageNum) !== false){
70870                     me.store.loadPage(pageNum);
70871                 }
70872             }
70873         } else if (k == e.HOME || k == e.END) {
70874             e.stopEvent();
70875             pageNum = k == e.HOME ? 1 : pageData.pageCount;
70876             field.setValue(pageNum);
70877         } else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN) {
70878             e.stopEvent();
70879             pageNum = me.readPageFromInput(pageData);
70880             if (pageNum) {
70881                 if (k == e.DOWN || k == e.PAGEDOWN) {
70882                     increment *= -1;
70883                 }
70884                 pageNum += increment;
70885                 if (pageNum >= 1 && pageNum <= pageData.pages) {
70886                     field.setValue(pageNum);
70887                 }
70888             }
70889         }
70890     },
70891
70892     
70893     beforeLoad : function(){
70894         if(this.rendered && this.refresh){
70895             this.refresh.disable();
70896         }
70897     },
70898
70899     
70900     doLoad : function(start){
70901         if(this.fireEvent('beforechange', this, o) !== false){
70902             this.store.load();
70903         }
70904     },
70905
70906     
70907     moveFirst : function(){
70908         if (this.fireEvent('beforechange', this, 1) !== false){
70909             this.store.loadPage(1);
70910         }
70911     },
70912
70913     
70914     movePrevious : function(){
70915         var me = this,
70916             prev = me.store.currentPage - 1;
70917
70918         if (prev > 0) {
70919             if (me.fireEvent('beforechange', me, prev) !== false) {
70920                 me.store.previousPage();
70921             }
70922         }
70923     },
70924
70925     
70926     moveNext : function(){
70927         var me = this,
70928             total = me.getPageData().pageCount,
70929             next = me.store.currentPage + 1;
70930
70931         if (next <= total) {
70932             if (me.fireEvent('beforechange', me, next) !== false) {
70933                 me.store.nextPage();
70934             }
70935         }
70936     },
70937
70938     
70939     moveLast : function(){
70940         var me = this,
70941             last = me.getPageData().pageCount;
70942
70943         if (me.fireEvent('beforechange', me, last) !== false) {
70944             me.store.loadPage(last);
70945         }
70946     },
70947
70948     
70949     doRefresh : function(){
70950         var me = this,
70951             current = me.store.currentPage;
70952
70953         if (me.fireEvent('beforechange', me, current) !== false) {
70954             me.store.loadPage(current);
70955         }
70956     },
70957
70958     
70959     bindStore : function(store, initial){
70960         var me = this;
70961
70962         if (!initial && me.store) {
70963             if(store !== me.store && me.store.autoDestroy){
70964                 me.store.destroyStore();
70965             }else{
70966                 me.store.un('beforeload', me.beforeLoad, me);
70967                 me.store.un('load', me.onLoad, me);
70968                 me.store.un('exception', me.onLoadError, me);
70969             }
70970             if(!store){
70971                 me.store = null;
70972             }
70973         }
70974         if (store) {
70975             store = Ext.data.StoreManager.lookup(store);
70976             store.on({
70977                 scope: me,
70978                 beforeload: me.beforeLoad,
70979                 load: me.onLoad,
70980                 exception: me.onLoadError
70981             });
70982         }
70983         me.store = store;
70984     },
70985
70986     
70987     unbind : function(store){
70988         this.bindStore(null);
70989     },
70990
70991     
70992     bind : function(store){
70993         this.bindStore(store);
70994     },
70995
70996     
70997     onDestroy : function(){
70998         this.bindStore(null);
70999         this.callParent();
71000     }
71001 });
71002
71003
71004 Ext.define('Ext.view.BoundList', {
71005     extend: 'Ext.view.View',
71006     alias: 'widget.boundlist',
71007     alternateClassName: 'Ext.BoundList',
71008     requires: ['Ext.layout.component.BoundList', 'Ext.toolbar.Paging'],
71009
71010     
71011     pageSize: 0,
71012
71013     
71014
71015     
71016     autoScroll: true,
71017     baseCls: Ext.baseCSSPrefix + 'boundlist',
71018     itemCls: Ext.baseCSSPrefix + 'boundlist-item',
71019     listItemCls: '',
71020     shadow: false,
71021     trackOver: true,
71022     refreshed: 0,
71023
71024     ariaRole: 'listbox',
71025
71026     componentLayout: 'boundlist',
71027
71028     renderTpl: ['<div id="{id}-listEl" class="list-ct"></div>'],
71029
71030     initComponent: function() {
71031         var me = this,
71032             baseCls = me.baseCls,
71033             itemCls = me.itemCls;
71034             
71035         me.selectedItemCls = baseCls + '-selected';
71036         me.overItemCls = baseCls + '-item-over';
71037         me.itemSelector = "." + itemCls;
71038
71039         if (me.floating) {
71040             me.addCls(baseCls + '-floating');
71041         }
71042
71043         if (!me.tpl) {
71044             
71045             
71046             me.tpl = Ext.create('Ext.XTemplate',
71047                 '<ul><tpl for=".">',
71048                     '<li role="option" class="' + itemCls + '">' + me.getInnerTpl(me.displayField) + '</li>',
71049                 '</tpl></ul>'
71050             );
71051         } else if (Ext.isString(me.tpl)) {
71052             me.tpl = Ext.create('Ext.XTemplate', me.tpl);
71053         }
71054
71055         if (me.pageSize) {
71056             me.pagingToolbar = me.createPagingToolbar();
71057         }
71058
71059         me.callParent();
71060
71061         me.addChildEls('listEl');
71062     },
71063
71064     createPagingToolbar: function() {
71065         return Ext.widget('pagingtoolbar', {
71066             pageSize: this.pageSize,
71067             store: this.store,
71068             border: false
71069         });
71070     },
71071
71072     onRender: function() {
71073         var me = this,
71074             toolbar = me.pagingToolbar;
71075         me.callParent(arguments);
71076         if (toolbar) {
71077             toolbar.render(me.el);
71078         }
71079     },
71080
71081     bindStore : function(store, initial) {
71082         var me = this,
71083             toolbar = me.pagingToolbar;
71084         me.callParent(arguments);
71085         if (toolbar) {
71086             toolbar.bindStore(store, initial);
71087         }
71088     },
71089
71090     getTargetEl: function() {
71091         return this.listEl || this.el;
71092     },
71093
71094     getInnerTpl: function(displayField) {
71095         return '{' + displayField + '}';
71096     },
71097
71098     refresh: function() {
71099         var me = this;
71100         me.callParent();
71101         if (me.isVisible()) {
71102             me.refreshed++;
71103             me.doComponentLayout();
71104             me.refreshed--;
71105         }
71106     },
71107
71108     initAria: function() {
71109         this.callParent();
71110
71111         var selModel = this.getSelectionModel(),
71112             mode     = selModel.getSelectionMode(),
71113             actionEl = this.getActionEl();
71114
71115         
71116         if (mode !== 'SINGLE') {
71117             actionEl.dom.setAttribute('aria-multiselectable', true);
71118         }
71119     },
71120
71121     onDestroy: function() {
71122         Ext.destroyMembers(this, 'pagingToolbar', 'listEl');
71123         this.callParent();
71124     }
71125 });
71126
71127
71128 Ext.define('Ext.view.BoundListKeyNav', {
71129     extend: 'Ext.util.KeyNav',
71130     requires: 'Ext.view.BoundList',
71131
71132     
71133
71134     constructor: function(el, config) {
71135         var me = this;
71136         me.boundList = config.boundList;
71137         me.callParent([el, Ext.apply({}, config, me.defaultHandlers)]);
71138     },
71139
71140     defaultHandlers: {
71141         up: function() {
71142             var me = this,
71143                 boundList = me.boundList,
71144                 allItems = boundList.all,
71145                 oldItem = boundList.highlightedItem,
71146                 oldItemIdx = oldItem ? boundList.indexOf(oldItem) : -1,
71147                 newItemIdx = oldItemIdx > 0 ? oldItemIdx - 1 : allItems.getCount() - 1; 
71148             me.highlightAt(newItemIdx);
71149         },
71150
71151         down: function() {
71152             var me = this,
71153                 boundList = me.boundList,
71154                 allItems = boundList.all,
71155                 oldItem = boundList.highlightedItem,
71156                 oldItemIdx = oldItem ? boundList.indexOf(oldItem) : -1,
71157                 newItemIdx = oldItemIdx < allItems.getCount() - 1 ? oldItemIdx + 1 : 0; 
71158             me.highlightAt(newItemIdx);
71159         },
71160
71161         pageup: function() {
71162             
71163         },
71164
71165         pagedown: function() {
71166             
71167         },
71168
71169         home: function() {
71170             this.highlightAt(0);
71171         },
71172
71173         end: function() {
71174             var me = this;
71175             me.highlightAt(me.boundList.all.getCount() - 1);
71176         },
71177
71178         enter: function(e) {
71179             this.selectHighlighted(e);
71180         }
71181     },
71182
71183     
71184     highlightAt: function(index) {
71185         var boundList = this.boundList,
71186             item = boundList.all.item(index);
71187         if (item) {
71188             item = item.dom;
71189             boundList.highlightItem(item);
71190             boundList.getTargetEl().scrollChildIntoView(item, false);
71191         }
71192     },
71193
71194     
71195     selectHighlighted: function(e) {
71196         var me = this,
71197             boundList = me.boundList,
71198             highlighted = boundList.highlightedItem,
71199             selModel = boundList.getSelectionModel();
71200         if (highlighted) {
71201             selModel.selectWithEvent(boundList.getRecord(highlighted), e);
71202         }
71203     }
71204
71205 });
71206
71207 Ext.define('Ext.form.field.ComboBox', {
71208     extend:'Ext.form.field.Picker',
71209     requires: ['Ext.util.DelayedTask', 'Ext.EventObject', 'Ext.view.BoundList', 'Ext.view.BoundListKeyNav', 'Ext.data.StoreManager'],
71210     alternateClassName: 'Ext.form.ComboBox',
71211     alias: ['widget.combobox', 'widget.combo'],
71212
71213     
71214     triggerCls: Ext.baseCSSPrefix + 'form-arrow-trigger',
71215
71216     
71217     hiddenDataCls: Ext.baseCSSPrefix + 'hide-display ' + Ext.baseCSSPrefix + 'form-data-hidden',
71218
71219     
71220     fieldSubTpl: [
71221         '<div class="{hiddenDataCls}" role="presentation"></div>',
71222         '<input id="{id}" type="{type}" ',
71223             '<tpl if="size">size="{size}" </tpl>',
71224             '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
71225             'class="{fieldCls} {typeCls}" autocomplete="off" />',
71226         '<div id="{cmpId}-triggerWrap" class="{triggerWrapCls}" role="presentation">',
71227             '{triggerEl}',
71228             '<div class="{clearCls}" role="presentation"></div>',
71229         '</div>',
71230         {
71231             compiled: true,
71232             disableFormats: true
71233         }
71234     ],
71235
71236     getSubTplData: function(){
71237         var me = this;
71238         Ext.applyIf(me.subTplData, {
71239             hiddenDataCls: me.hiddenDataCls
71240         });
71241         return me.callParent(arguments);
71242     },
71243
71244     afterRender: function(){
71245         var me = this;
71246         me.callParent(arguments);
71247         me.setHiddenValue(me.value);
71248     },
71249
71250     
71251
71252     
71253     multiSelect: false,
71254
71255     
71256     delimiter: ', ',
71257
71258     
71259     displayField: 'text',
71260
71261     
71262
71263     
71264     triggerAction: 'all',
71265
71266     
71267     allQuery: '',
71268
71269     
71270     queryParam: 'query',
71271
71272     
71273     queryMode: 'remote',
71274
71275     queryCaching: true,
71276
71277     
71278     pageSize: 0,
71279
71280     
71281
71282     
71283
71284     
71285     autoSelect: true,
71286
71287     
71288     typeAhead: false,
71289
71290     
71291     typeAheadDelay: 250,
71292
71293     
71294     selectOnTab: true,
71295
71296     
71297     forceSelection: false,
71298
71299     
71300
71301     
71302
71303     
71304     defaultListConfig: {
71305         emptyText: '',
71306         loadingText: 'Loading...',
71307         loadingHeight: 70,
71308         minWidth: 70,
71309         maxHeight: 300,
71310         shadow: 'sides'
71311     },
71312
71313     
71314
71315     
71316
71317     
71318     ignoreSelection: 0,
71319
71320     initComponent: function() {
71321         var me = this,
71322             isDefined = Ext.isDefined,
71323             store = me.store,
71324             transform = me.transform,
71325             transformSelect, isLocalMode;
71326
71327         Ext.applyIf(me.renderSelectors, {
71328             hiddenDataEl: '.' + me.hiddenDataCls.split(' ').join('.')
71329         });
71330         
71331
71332         this.addEvents(
71333             
71334             'beforequery',
71335
71336             
71337             'select',
71338
71339             
71340             'beforeselect',
71341
71342             
71343             'beforedeselect'
71344         );
71345
71346         
71347         if (transform) {
71348             transformSelect = Ext.getDom(transform);
71349             if (transformSelect) {
71350                 store = Ext.Array.map(Ext.Array.from(transformSelect.options), function(option) {
71351                     return [option.value, option.text];
71352                 });
71353                 if (!me.name) {
71354                     me.name = transformSelect.name;
71355                 }
71356                 if (!('value' in me)) {
71357                     me.value = transformSelect.value;
71358                 }
71359             }
71360         }
71361
71362         me.bindStore(store || 'ext-empty-store', true);
71363         store = me.store;
71364         if (store.autoCreated) {
71365             me.queryMode = 'local';
71366             me.valueField = me.displayField = 'field1';
71367             if (!store.expanded) {
71368                 me.displayField = 'field2';
71369             }
71370         }
71371
71372
71373         if (!isDefined(me.valueField)) {
71374             me.valueField = me.displayField;
71375         }
71376
71377         isLocalMode = me.queryMode === 'local';
71378         if (!isDefined(me.queryDelay)) {
71379             me.queryDelay = isLocalMode ? 10 : 500;
71380         }
71381         if (!isDefined(me.minChars)) {
71382             me.minChars = isLocalMode ? 0 : 4;
71383         }
71384
71385         if (!me.displayTpl) {
71386             me.displayTpl = Ext.create('Ext.XTemplate',
71387                 '<tpl for=".">' +
71388                     '{[typeof values === "string" ? values : values["' + me.displayField + '"]]}' +
71389                     '<tpl if="xindex < xcount">' + me.delimiter + '</tpl>' +
71390                 '</tpl>'
71391             );
71392         } else if (Ext.isString(me.displayTpl)) {
71393             me.displayTpl = Ext.create('Ext.XTemplate', me.displayTpl);
71394         }
71395
71396         me.callParent();
71397
71398         me.doQueryTask = Ext.create('Ext.util.DelayedTask', me.doRawQuery, me);
71399
71400         
71401         if (me.store.getCount() > 0) {
71402             me.setValue(me.value);
71403         }
71404
71405         
71406         if (transformSelect) {
71407             me.render(transformSelect.parentNode, transformSelect);
71408             Ext.removeNode(transformSelect);
71409             delete me.renderTo;
71410         }
71411     },
71412
71413     
71414     getStore : function(){
71415         return this.store;
71416     },
71417
71418     beforeBlur: function() {
71419         this.doQueryTask.cancel();
71420         this.assertValue();
71421     },
71422
71423     
71424     assertValue: function() {
71425         var me = this,
71426             value = me.getRawValue(),
71427             rec;
71428
71429         if (me.forceSelection) {
71430             if (me.multiSelect) {
71431                 
71432                 
71433                 if (value !== me.getDisplayValue()) {
71434                     me.setValue(me.lastSelection);
71435                 }
71436             } else {
71437                 
71438                 
71439                 rec = me.findRecordByDisplay(value);
71440                 if (rec) {
71441                     me.select(rec);
71442                 } else {
71443                     me.setValue(me.lastSelection);
71444                 }
71445             }
71446         }
71447         me.collapse();
71448     },
71449
71450     onTypeAhead: function() {
71451         var me = this,
71452             displayField = me.displayField,
71453             record = me.store.findRecord(displayField, me.getRawValue()),
71454             boundList = me.getPicker(),
71455             newValue, len, selStart;
71456
71457         if (record) {
71458             newValue = record.get(displayField);
71459             len = newValue.length;
71460             selStart = me.getRawValue().length;
71461
71462             boundList.highlightItem(boundList.getNode(record));
71463
71464             if (selStart !== 0 && selStart !== len) {
71465                 me.setRawValue(newValue);
71466                 me.selectText(selStart, newValue.length);
71467             }
71468         }
71469     },
71470
71471     
71472     
71473     resetToDefault: function() {
71474
71475     },
71476
71477     bindStore: function(store, initial) {
71478         var me = this,
71479             oldStore = me.store;
71480
71481         
71482         
71483         if (oldStore && !initial) {
71484             if (oldStore !== store && oldStore.autoDestroy) {
71485                 oldStore.destroyStore();
71486             } else {
71487                 oldStore.un({
71488                     scope: me,
71489                     load: me.onLoad,
71490                     exception: me.collapse
71491                 });
71492             }
71493             if (!store) {
71494                 me.store = null;
71495                 if (me.picker) {
71496                     me.picker.bindStore(null);
71497                 }
71498             }
71499         }
71500         if (store) {
71501             if (!initial) {
71502                 me.resetToDefault();
71503             }
71504
71505             me.store = Ext.data.StoreManager.lookup(store);
71506             me.store.on({
71507                 scope: me,
71508                 load: me.onLoad,
71509                 exception: me.collapse
71510             });
71511
71512             if (me.picker) {
71513                 me.picker.bindStore(store);
71514             }
71515         }
71516     },
71517
71518     onLoad: function() {
71519         var me = this,
71520             value = me.value;
71521
71522         
71523         if (me.rawQuery) {
71524             me.rawQuery = false;
71525             me.syncSelection();
71526             if (me.picker && !me.picker.getSelectionModel().hasSelection()) {
71527                 me.doAutoSelect();
71528             }
71529         }
71530         
71531         else {
71532             
71533             if (me.value) {
71534                 me.setValue(me.value);
71535             } else {
71536                 
71537                 
71538                 if (me.store.getCount()) {
71539                     me.doAutoSelect();
71540                 } else {
71541                     me.setValue('');
71542                 }
71543             }
71544         }
71545     },
71546
71547     
71548     doRawQuery: function() {
71549         this.doQuery(this.getRawValue(), false, true);
71550     },
71551
71552     
71553     doQuery: function(queryString, forceAll, rawQuery) {
71554         queryString = queryString || '';
71555
71556         
71557         
71558         var me = this,
71559             qe = {
71560                 query: queryString,
71561                 forceAll: forceAll,
71562                 combo: me,
71563                 cancel: false
71564             },
71565             store = me.store,
71566             isLocalMode = me.queryMode === 'local';
71567
71568         if (me.fireEvent('beforequery', qe) === false || qe.cancel) {
71569             return false;
71570         }
71571
71572         
71573         queryString = qe.query;
71574         forceAll = qe.forceAll;
71575
71576         
71577         if (forceAll || (queryString.length >= me.minChars)) {
71578             
71579             me.expand();
71580
71581             
71582             if (!me.queryCaching || me.lastQuery !== queryString) {
71583                 me.lastQuery = queryString;
71584
71585                 if (isLocalMode) {
71586                     
71587                     if (forceAll) {
71588                         store.clearFilter();
71589                     } else {
71590                         
71591                         store.clearFilter(true);
71592                         store.filter(me.displayField, queryString);
71593                     }
71594                 } else {
71595                     
71596                     me.rawQuery = rawQuery;
71597
71598                     
71599                     
71600                     if (me.pageSize) {
71601                         
71602                         me.loadPage(1);
71603                     } else {
71604                         store.load({
71605                             params: me.getParams(queryString)
71606                         });
71607                     }
71608                 }
71609             }
71610
71611             
71612             if (me.getRawValue() !== me.getDisplayValue()) {
71613                 me.ignoreSelection++;
71614                 me.picker.getSelectionModel().deselectAll();
71615                 me.ignoreSelection--;
71616             }
71617
71618             if (isLocalMode) {
71619                 me.doAutoSelect();
71620             }
71621             if (me.typeAhead) {
71622                 me.doTypeAhead();
71623             }
71624         }
71625         return true;
71626     },
71627
71628     loadPage: function(pageNum){
71629         this.store.loadPage(pageNum, {
71630             params: this.getParams(this.lastQuery)
71631         });
71632     },
71633
71634     onPageChange: function(toolbar, newPage){
71635         
71636         this.loadPage(newPage);
71637         return false;
71638     },
71639
71640     
71641     getParams: function(queryString) {
71642         var params = {},
71643             param = this.queryParam;
71644
71645         if (param) {
71646             params[param] = queryString;
71647         }
71648         return params;
71649     },
71650
71651     
71652     doAutoSelect: function() {
71653         var me = this,
71654             picker = me.picker,
71655             lastSelected, itemNode;
71656         if (picker && me.autoSelect && me.store.getCount() > 0) {
71657             
71658             lastSelected = picker.getSelectionModel().lastSelected;
71659             itemNode = picker.getNode(lastSelected || 0);
71660             if (itemNode) {
71661                 picker.highlightItem(itemNode);
71662                 picker.listEl.scrollChildIntoView(itemNode, false);
71663             }
71664         }
71665     },
71666
71667     doTypeAhead: function() {
71668         if (!this.typeAheadTask) {
71669             this.typeAheadTask = Ext.create('Ext.util.DelayedTask', this.onTypeAhead, this);
71670         }
71671         if (this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE) {
71672             this.typeAheadTask.delay(this.typeAheadDelay);
71673         }
71674     },
71675
71676     onTriggerClick: function() {
71677         var me = this;
71678         if (!me.readOnly && !me.disabled) {
71679             if (me.isExpanded) {
71680                 me.collapse();
71681             } else {
71682                 me.onFocus({});
71683                 if (me.triggerAction === 'all') {
71684                     me.doQuery(me.allQuery, true);
71685                 } else {
71686                     me.doQuery(me.getRawValue(), false, true);
71687                 }
71688             }
71689             me.inputEl.focus();
71690         }
71691     },
71692
71693
71694     
71695     onKeyUp: function(e, t) {
71696         var me = this,
71697             key = e.getKey();
71698
71699         if (!me.readOnly && !me.disabled && me.editable) {
71700             me.lastKey = key;
71701             
71702             
71703
71704             
71705             if (!e.isSpecialKey() || key == e.BACKSPACE || key == e.DELETE) {
71706                 me.doQueryTask.delay(me.queryDelay);
71707             }
71708         }
71709
71710         if (me.enableKeyEvents) {
71711             me.callParent(arguments);
71712         }
71713     },
71714
71715     initEvents: function() {
71716         var me = this;
71717         me.callParent();
71718
71719         
71720         if (!me.enableKeyEvents) {
71721             me.mon(me.inputEl, 'keyup', me.onKeyUp, me);
71722         }
71723     },
71724     
71725     onDestroy: function(){
71726         this.bindStore(null);
71727         this.callParent();    
71728     },
71729
71730     createPicker: function() {
71731         var me = this,
71732             picker,
71733             menuCls = Ext.baseCSSPrefix + 'menu',
71734             opts = Ext.apply({
71735                 pickerField: me,
71736                 selModel: {
71737                     mode: me.multiSelect ? 'SIMPLE' : 'SINGLE'
71738                 },
71739                 floating: true,
71740                 hidden: true,
71741                 ownerCt: me.ownerCt,
71742                 cls: me.el.up('.' + menuCls) ? menuCls : '',
71743                 store: me.store,
71744                 displayField: me.displayField,
71745                 focusOnToFront: false,
71746                 pageSize: me.pageSize,
71747                 tpl: me.tpl
71748             }, me.listConfig, me.defaultListConfig);
71749
71750         picker = me.picker = Ext.create('Ext.view.BoundList', opts);
71751         if (me.pageSize) {
71752             picker.pagingToolbar.on('beforechange', me.onPageChange, me);
71753         }
71754
71755         me.mon(picker, {
71756             itemclick: me.onItemClick,
71757             refresh: me.onListRefresh,
71758             scope: me
71759         });
71760
71761         me.mon(picker.getSelectionModel(), {
71762             'beforeselect': me.onBeforeSelect,
71763             'beforedeselect': me.onBeforeDeselect,
71764             'selectionchange': me.onListSelectionChange,
71765             scope: me
71766         });
71767
71768         return picker;
71769     },
71770
71771     alignPicker: function(){
71772         var me = this,
71773             picker = me.picker,
71774             heightAbove = me.getPosition()[1] - Ext.getBody().getScroll().top,
71775             heightBelow = Ext.Element.getViewHeight() - heightAbove - me.getHeight(),
71776             space = Math.max(heightAbove, heightBelow);
71777
71778         me.callParent();
71779         if (picker.getHeight() > space) {
71780             picker.setHeight(space - 5); 
71781             me.doAlign();
71782         }
71783     },
71784
71785     onListRefresh: function() {
71786         this.alignPicker();
71787         this.syncSelection();
71788     },
71789
71790     onItemClick: function(picker, record){
71791         
71792         var me = this,
71793             lastSelection = me.lastSelection,
71794             valueField = me.valueField,
71795             selected;
71796
71797         if (!me.multiSelect && lastSelection) {
71798             selected = lastSelection[0];
71799             if (selected && (record.get(valueField) === selected.get(valueField))) {
71800                 
71801                 me.displayTplData = [record.data];
71802                 me.setRawValue(me.getDisplayValue());
71803                 me.collapse();
71804             }
71805         }
71806     },
71807
71808     onBeforeSelect: function(list, record) {
71809         return this.fireEvent('beforeselect', this, record, record.index);
71810     },
71811
71812     onBeforeDeselect: function(list, record) {
71813         return this.fireEvent('beforedeselect', this, record, record.index);
71814     },
71815
71816     onListSelectionChange: function(list, selectedRecords) {
71817         var me = this,
71818             isMulti = me.multiSelect,
71819             hasRecords = selectedRecords.length > 0;
71820         
71821         
71822         if (!me.ignoreSelection && me.isExpanded) {
71823             if (!isMulti) {
71824                 Ext.defer(me.collapse, 1, me);
71825             }
71826             
71827             if (isMulti || hasRecords) {
71828                 me.setValue(selectedRecords, false);
71829             }
71830             if (hasRecords) {
71831                 me.fireEvent('select', me, selectedRecords);
71832             }
71833             me.inputEl.focus();
71834         }
71835     },
71836
71837     
71838     onExpand: function() {
71839         var me = this,
71840             keyNav = me.listKeyNav,
71841             selectOnTab = me.selectOnTab,
71842             picker = me.getPicker();
71843
71844         
71845         if (keyNav) {
71846             keyNav.enable();
71847         } else {
71848             keyNav = me.listKeyNav = Ext.create('Ext.view.BoundListKeyNav', this.inputEl, {
71849                 boundList: picker,
71850                 forceKeyDown: true,
71851                 tab: function(e) {
71852                     if (selectOnTab) {
71853                         this.selectHighlighted(e);
71854                         me.triggerBlur();
71855                     }
71856                     
71857                     return true;
71858                 }
71859             });
71860         }
71861
71862         
71863         if (selectOnTab) {
71864             me.ignoreMonitorTab = true;
71865         }
71866
71867         Ext.defer(keyNav.enable, 1, keyNav); 
71868         me.inputEl.focus();
71869     },
71870
71871     
71872     onCollapse: function() {
71873         var me = this,
71874             keyNav = me.listKeyNav;
71875         if (keyNav) {
71876             keyNav.disable();
71877             me.ignoreMonitorTab = false;
71878         }
71879     },
71880
71881     
71882     select: function(r) {
71883         this.setValue(r, true);
71884     },
71885
71886     
71887     findRecord: function(field, value) {
71888         var ds = this.store,
71889             idx = ds.findExact(field, value);
71890         return idx !== -1 ? ds.getAt(idx) : false;
71891     },
71892
71893     
71894     findRecordByValue: function(value) {
71895         return this.findRecord(this.valueField, value);
71896     },
71897
71898     
71899     findRecordByDisplay: function(value) {
71900         return this.findRecord(this.displayField, value);
71901     },
71902
71903     
71904     setValue: function(value, doSelect) {
71905         var me = this,
71906             valueNotFoundText = me.valueNotFoundText,
71907             inputEl = me.inputEl,
71908             i, len, record,
71909             models = [],
71910             displayTplData = [],
71911             processedValue = [];
71912
71913         if (me.store.loading) {
71914             
71915             me.value = value;
71916             me.setHiddenValue(me.value);
71917             return me;
71918         }
71919
71920         
71921         value = Ext.Array.from(value);
71922
71923         
71924         for (i = 0, len = value.length; i < len; i++) {
71925             record = value[i];
71926             if (!record || !record.isModel) {
71927                 record = me.findRecordByValue(record);
71928             }
71929             
71930             if (record) {
71931                 models.push(record);
71932                 displayTplData.push(record.data);
71933                 processedValue.push(record.get(me.valueField));
71934             }
71935             
71936             
71937             else {
71938                 
71939                 if (!me.forceSelection) {
71940                     displayTplData.push(value[i]);
71941                     processedValue.push(value[i]);
71942                 }
71943                 
71944                 else if (Ext.isDefined(valueNotFoundText)) {
71945                     displayTplData.push(valueNotFoundText);
71946                 }
71947             }
71948         }
71949
71950         
71951         me.setHiddenValue(processedValue);
71952         me.value = me.multiSelect ? processedValue : processedValue[0];
71953         if (!Ext.isDefined(me.value)) {
71954             me.value = null;
71955         }
71956         me.displayTplData = displayTplData; 
71957         me.lastSelection = me.valueModels = models;
71958
71959         if (inputEl && me.emptyText && !Ext.isEmpty(value)) {
71960             inputEl.removeCls(me.emptyCls);
71961         }
71962
71963         
71964         me.setRawValue(me.getDisplayValue());
71965         me.checkChange();
71966
71967         if (doSelect !== false) {
71968             me.syncSelection();
71969         }
71970         me.applyEmptyText();
71971
71972         return me;
71973     },
71974
71975     
71976     setHiddenValue: function(values){
71977         var me = this, i;
71978         if (!me.hiddenDataEl) {
71979             return;
71980         }
71981         values = Ext.Array.from(values);
71982         var dom = me.hiddenDataEl.dom,
71983             childNodes = dom.childNodes,
71984             input = childNodes[0],
71985             valueCount = values.length,
71986             childrenCount = childNodes.length;
71987         
71988         if (!input && valueCount > 0) {
71989             me.hiddenDataEl.update(Ext.DomHelper.markup({tag:'input', type:'hidden', name:me.name}));
71990             childrenCount = 1;
71991             input = dom.firstChild;
71992         }
71993         while (childrenCount > valueCount) {
71994             dom.removeChild(childNodes[0]);
71995             -- childrenCount;
71996         }
71997         while (childrenCount < valueCount) {
71998             dom.appendChild(input.cloneNode(true));
71999             ++ childrenCount;
72000         }
72001         for (i = 0; i < valueCount; i++) {
72002             childNodes[i].value = values[i];
72003         }
72004     },
72005
72006     
72007     getDisplayValue: function() {
72008         return this.displayTpl.apply(this.displayTplData);
72009     },
72010
72011     getValue: function() {
72012         
72013         
72014         
72015         var me = this,
72016             picker = me.picker,
72017             rawValue = me.getRawValue(), 
72018             value = me.value; 
72019
72020         if (me.getDisplayValue() !== rawValue) {
72021             value = rawValue;
72022             me.value = me.displayTplData = me.valueModels = null;
72023             if (picker) {
72024                 me.ignoreSelection++;
72025                 picker.getSelectionModel().deselectAll();
72026                 me.ignoreSelection--;
72027             }
72028         }
72029
72030         return value;
72031     },
72032
72033     getSubmitValue: function() {
72034         return this.getValue();
72035     },
72036
72037     isEqual: function(v1, v2) {
72038         var fromArray = Ext.Array.from,
72039             i, len;
72040
72041         v1 = fromArray(v1);
72042         v2 = fromArray(v2);
72043         len = v1.length;
72044
72045         if (len !== v2.length) {
72046             return false;
72047         }
72048
72049         for(i = 0; i < len; i++) {
72050             if (v2[i] !== v1[i]) {
72051                 return false;
72052             }
72053         }
72054
72055         return true;
72056     },
72057
72058     
72059     clearValue: function() {
72060         this.setValue([]);
72061     },
72062
72063     
72064     syncSelection: function() {
72065         var me = this,
72066             ExtArray = Ext.Array,
72067             picker = me.picker,
72068             selection, selModel;
72069         if (picker) {
72070             
72071             selection = [];
72072             ExtArray.forEach(me.valueModels || [], function(value) {
72073                 if (value && value.isModel && me.store.indexOf(value) >= 0) {
72074                     selection.push(value);
72075                 }
72076             });
72077
72078             
72079             me.ignoreSelection++;
72080             selModel = picker.getSelectionModel();
72081             selModel.deselectAll();
72082             if (selection.length) {
72083                 selModel.select(selection);
72084             }
72085             me.ignoreSelection--;
72086         }
72087     }
72088 });
72089
72090
72091 Ext.define('Ext.picker.Month', {
72092     extend: 'Ext.Component',
72093     requires: ['Ext.XTemplate', 'Ext.util.ClickRepeater', 'Ext.Date', 'Ext.button.Button'],
72094     alias: 'widget.monthpicker',
72095     alternateClassName: 'Ext.MonthPicker',
72096
72097     renderTpl: [
72098         '<div id="{id}-bodyEl" class="{baseCls}-body">',
72099           '<div class="{baseCls}-months">',
72100               '<tpl for="months">',
72101                   '<div class="{parent.baseCls}-item {parent.baseCls}-month"><a href="#" hidefocus="on">{.}</a></div>',
72102               '</tpl>',
72103           '</div>',
72104           '<div class="{baseCls}-years">',
72105               '<div class="{baseCls}-yearnav">',
72106                   '<button id="{id}-prevEl" class="{baseCls}-yearnav-prev"></button>',
72107                   '<button id="{id}-nextEl" class="{baseCls}-yearnav-next"></button>',
72108               '</div>',
72109               '<tpl for="years">',
72110                   '<div class="{parent.baseCls}-item {parent.baseCls}-year"><a href="#" hidefocus="on">{.}</a></div>',
72111               '</tpl>',
72112           '</div>',
72113           '<div class="' + Ext.baseCSSPrefix + 'clear"></div>',
72114         '</div>',
72115         '<tpl if="showButtons">',
72116           '<div id="{id}-buttonsEl" class="{baseCls}-buttons"></div>',
72117         '</tpl>'
72118     ],
72119
72120     
72121     okText: 'OK',
72122
72123     
72124     cancelText: 'Cancel',
72125
72126     
72127     baseCls: Ext.baseCSSPrefix + 'monthpicker',
72128
72129     
72130     showButtons: true,
72131
72132     
72133
72134     
72135     width: 178,
72136
72137     
72138     smallCls: Ext.baseCSSPrefix + 'monthpicker-small',
72139
72140     
72141     totalYears: 10,
72142     yearOffset: 5, 
72143     monthOffset: 6, 
72144
72145     
72146     initComponent: function(){
72147         var me = this;
72148
72149         me.selectedCls = me.baseCls + '-selected';
72150         me.addEvents(
72151             
72152             'cancelclick',
72153
72154             
72155             'monthclick',
72156
72157             
72158             'monthdblclick',
72159
72160             
72161             'okclick',
72162
72163             
72164             'select',
72165
72166             
72167             'yearclick',
72168
72169             
72170             'yeardblclick'
72171         );
72172         if (me.small) {
72173             me.addCls(me.smallCls);
72174         }
72175         me.setValue(me.value);
72176         me.activeYear = me.getYear(new Date().getFullYear() - 4, -4);
72177         this.callParent();
72178     },
72179
72180     
72181     onRender: function(ct, position){
72182         var me = this,
72183             i = 0,
72184             months = [],
72185             shortName = Ext.Date.getShortMonthName,
72186             monthLen = me.monthOffset;
72187
72188         for (; i < monthLen; ++i) {
72189             months.push(shortName(i), shortName(i + monthLen));
72190         }
72191
72192         Ext.apply(me.renderData, {
72193             months: months,
72194             years: me.getYears(),
72195             showButtons: me.showButtons
72196         });
72197
72198         me.addChildEls('bodyEl', 'prevEl', 'nextEl', 'buttonsEl');
72199
72200         me.callParent(arguments);
72201     },
72202
72203     
72204     afterRender: function(){
72205         var me = this,
72206             body = me.bodyEl,
72207             buttonsEl = me.buttonsEl;
72208
72209         me.callParent();
72210
72211         me.mon(body, 'click', me.onBodyClick, me);
72212         me.mon(body, 'dblclick', me.onBodyClick, me);
72213
72214         
72215         me.years = body.select('.' + me.baseCls + '-year a');
72216         me.months = body.select('.' + me.baseCls + '-month a');
72217
72218         if (me.showButtons) {
72219             me.okBtn = Ext.create('Ext.button.Button', {
72220                 text: me.okText,
72221                 renderTo: buttonsEl,
72222                 handler: me.onOkClick,
72223                 scope: me
72224             });
72225             me.cancelBtn = Ext.create('Ext.button.Button', {
72226                 text: me.cancelText,
72227                 renderTo: buttonsEl,
72228                 handler: me.onCancelClick,
72229                 scope: me
72230             });
72231         }
72232
72233         me.backRepeater = Ext.create('Ext.util.ClickRepeater', me.prevEl, {
72234             handler: Ext.Function.bind(me.adjustYear, me, [-me.totalYears])
72235         });
72236
72237         me.prevEl.addClsOnOver(me.baseCls + '-yearnav-prev-over');
72238         me.nextRepeater = Ext.create('Ext.util.ClickRepeater', me.nextEl, {
72239             handler: Ext.Function.bind(me.adjustYear, me, [me.totalYears])
72240         });
72241         me.nextEl.addClsOnOver(me.baseCls + '-yearnav-next-over');
72242         me.updateBody();
72243     },
72244
72245     
72246     setValue: function(value){
72247         var me = this,
72248             active = me.activeYear,
72249             offset = me.monthOffset,
72250             year,
72251             index;
72252
72253         if (!value) {
72254             me.value = [null, null];
72255         } else if (Ext.isDate(value)) {
72256             me.value = [value.getMonth(), value.getFullYear()];
72257         } else {
72258             me.value = [value[0], value[1]];
72259         }
72260
72261         if (me.rendered) {
72262             year = me.value[1];
72263             if (year !== null) {
72264                 if ((year < active || year > active + me.yearOffset)) {
72265                     me.activeYear = year - me.yearOffset + 1;
72266                 }
72267             }
72268             me.updateBody();
72269         }
72270
72271         return me;
72272     },
72273
72274     
72275     getValue: function(){
72276         return this.value;
72277     },
72278
72279     
72280     hasSelection: function(){
72281         var value = this.value;
72282         return value[0] !== null && value[1] !== null;
72283     },
72284
72285     
72286     getYears: function(){
72287         var me = this,
72288             offset = me.yearOffset,
72289             start = me.activeYear, 
72290             end = start + offset,
72291             i = start,
72292             years = [];
72293
72294         for (; i < end; ++i) {
72295             years.push(i, i + offset);
72296         }
72297
72298         return years;
72299     },
72300
72301     
72302     updateBody: function(){
72303         var me = this,
72304             years = me.years,
72305             months = me.months,
72306             yearNumbers = me.getYears(),
72307             cls = me.selectedCls,
72308             value = me.getYear(null),
72309             month = me.value[0],
72310             monthOffset = me.monthOffset,
72311             year;
72312
72313         if (me.rendered) {
72314             years.removeCls(cls);
72315             months.removeCls(cls);
72316             years.each(function(el, all, index){
72317                 year = yearNumbers[index];
72318                 el.dom.innerHTML = year;
72319                 if (year == value) {
72320                     el.dom.className = cls;
72321                 }
72322             });
72323             if (month !== null) {
72324                 if (month < monthOffset) {
72325                     month = month * 2;
72326                 } else {
72327                     month = (month - monthOffset) * 2 + 1;
72328                 }
72329                 months.item(month).addCls(cls);
72330             }
72331         }
72332     },
72333
72334     
72335     getYear: function(defaultValue, offset) {
72336         var year = this.value[1];
72337         offset = offset || 0;
72338         return year === null ? defaultValue : year + offset;
72339     },
72340
72341     
72342     onBodyClick: function(e, t) {
72343         var me = this,
72344             isDouble = e.type == 'dblclick';
72345
72346         if (e.getTarget('.' + me.baseCls + '-month')) {
72347             e.stopEvent();
72348             me.onMonthClick(t, isDouble);
72349         } else if (e.getTarget('.' + me.baseCls + '-year')) {
72350             e.stopEvent();
72351             me.onYearClick(t, isDouble);
72352         }
72353     },
72354
72355     
72356     adjustYear: function(offset){
72357         if (typeof offset != 'number') {
72358             offset = this.totalYears;
72359         }
72360         this.activeYear += offset;
72361         this.updateBody();
72362     },
72363
72364     
72365     onOkClick: function(){
72366         this.fireEvent('okclick', this, this.value);
72367     },
72368
72369     
72370     onCancelClick: function(){
72371         this.fireEvent('cancelclick', this);
72372     },
72373
72374     
72375     onMonthClick: function(target, isDouble){
72376         var me = this;
72377         me.value[0] = me.resolveOffset(me.months.indexOf(target), me.monthOffset);
72378         me.updateBody();
72379         me.fireEvent('month' + (isDouble ? 'dbl' : '') + 'click', me, me.value);
72380         me.fireEvent('select', me, me.value);
72381     },
72382
72383     
72384     onYearClick: function(target, isDouble){
72385         var me = this;
72386         me.value[1] = me.activeYear + me.resolveOffset(me.years.indexOf(target), me.yearOffset);
72387         me.updateBody();
72388         me.fireEvent('year' + (isDouble ? 'dbl' : '') + 'click', me, me.value);
72389         me.fireEvent('select', me, me.value);
72390
72391     },
72392
72393     
72394     resolveOffset: function(index, offset){
72395         if (index % 2 === 0) {
72396             return (index / 2);
72397         } else {
72398             return offset + Math.floor(index / 2);
72399         }
72400     },
72401
72402     
72403     beforeDestroy: function(){
72404         var me = this;
72405         me.years = me.months = null;
72406         Ext.destroyMembers(me, 'backRepeater', 'nextRepeater', 'okBtn', 'cancelBtn');
72407         me.callParent();
72408     }
72409 });
72410
72411
72412 Ext.define('Ext.picker.Date', {
72413     extend: 'Ext.Component',
72414     requires: [
72415         'Ext.XTemplate',
72416         'Ext.button.Button',
72417         'Ext.button.Split',
72418         'Ext.util.ClickRepeater',
72419         'Ext.util.KeyNav',
72420         'Ext.EventObject',
72421         'Ext.fx.Manager',
72422         'Ext.picker.Month'
72423     ],
72424     alias: 'widget.datepicker',
72425     alternateClassName: 'Ext.DatePicker',
72426
72427     renderTpl: [
72428         '<div class="{cls}" id="{id}" role="grid" title="{ariaTitle} {value:this.longDay}">',
72429             '<div role="presentation" class="{baseCls}-header">',
72430                 '<div class="{baseCls}-prev"><a id="{id}-prevEl" href="#" role="button" title="{prevText}"></a></div>',
72431                 '<div class="{baseCls}-month" id="{id}-middleBtnEl"></div>',
72432                 '<div class="{baseCls}-next"><a id="{id}-nextEl" href="#" role="button" title="{nextText}"></a></div>',
72433             '</div>',
72434             '<table id="{id}-eventEl" class="{baseCls}-inner" cellspacing="0" role="presentation">',
72435                 '<thead role="presentation"><tr role="presentation">',
72436                     '<tpl for="dayNames">',
72437                         '<th role="columnheader" title="{.}"><span>{.:this.firstInitial}</span></th>',
72438                     '</tpl>',
72439                 '</tr></thead>',
72440                 '<tbody role="presentation"><tr role="presentation">',
72441                     '<tpl for="days">',
72442                         '{#:this.isEndOfWeek}',
72443                         '<td role="gridcell" id="{[Ext.id()]}">',
72444                             '<a role="presentation" href="#" hidefocus="on" class="{parent.baseCls}-date" tabIndex="1">',
72445                                 '<em role="presentation"><span role="presentation"></span></em>',
72446                             '</a>',
72447                         '</td>',
72448                     '</tpl>',
72449                 '</tr></tbody>',
72450             '</table>',
72451             '<tpl if="showToday">',
72452                 '<div id="{id}-footerEl" role="presentation" class="{baseCls}-footer"></div>',
72453             '</tpl>',
72454         '</div>',
72455         {
72456             firstInitial: function(value) {
72457                 return value.substr(0,1);
72458             },
72459             isEndOfWeek: function(value) {
72460                 
72461                 
72462                 value--;
72463                 var end = value % 7 === 0 && value !== 0;
72464                 return end ? '</tr><tr role="row">' : '';
72465             },
72466             longDay: function(value){
72467                 return Ext.Date.format(value, this.longDayFormat);
72468             }
72469         }
72470     ],
72471
72472     ariaTitle: 'Date Picker',
72473
72474     
72475     todayText : 'Today',
72476
72477     
72478
72479     
72480
72481     
72482     todayTip : '{0} (Spacebar)',
72483
72484     
72485     minText : 'This date is before the minimum date',
72486
72487     
72488     maxText : 'This date is after the maximum date',
72489
72490     
72491
72492     
72493     disabledDaysText : 'Disabled',
72494
72495     
72496     disabledDatesText : 'Disabled',
72497
72498     
72499
72500     
72501
72502     
72503     nextText : 'Next Month (Control+Right)',
72504
72505     
72506     prevText : 'Previous Month (Control+Left)',
72507
72508     
72509     monthYearText : 'Choose a month (Control+Up/Down to move years)',
72510
72511     
72512     startDay : 0,
72513
72514     
72515     showToday : true,
72516
72517     
72518
72519     
72520
72521     
72522
72523     
72524
72525     
72526
72527     
72528     disableAnim: false,
72529
72530     
72531     baseCls: Ext.baseCSSPrefix + 'datepicker',
72532
72533     
72534
72535     
72536
72537     
72538     longDayFormat: 'F d, Y',
72539
72540     
72541
72542     
72543     focusOnShow: false,
72544
72545     
72546     
72547     focusOnSelect: true,
72548
72549     width: 178,
72550
72551     
72552     
72553     initHour: 12, 
72554
72555     numDays: 42,
72556
72557     
72558     initComponent : function() {
72559         var me = this,
72560             clearTime = Ext.Date.clearTime;
72561
72562         me.selectedCls = me.baseCls + '-selected';
72563         me.disabledCellCls = me.baseCls + '-disabled';
72564         me.prevCls = me.baseCls + '-prevday';
72565         me.activeCls = me.baseCls + '-active';
72566         me.nextCls = me.baseCls + '-prevday';
72567         me.todayCls = me.baseCls + '-today';
72568         me.dayNames = me.dayNames.slice(me.startDay).concat(me.dayNames.slice(0, me.startDay));
72569         this.callParent();
72570
72571         me.value = me.value ?
72572                  clearTime(me.value, true) : clearTime(new Date());
72573
72574         me.addEvents(
72575             
72576             'select'
72577         );
72578
72579         me.initDisabledDays();
72580     },
72581
72582     
72583     onRender : function(container, position){
72584         
72585
72586         var me = this,
72587             days = new Array(me.numDays),
72588             today = Ext.Date.format(new Date(), me.format);
72589
72590         Ext.applyIf(me, {
72591             renderData: {}
72592         });
72593
72594         Ext.apply(me.renderData, {
72595             dayNames: me.dayNames,
72596             ariaTitle: me.ariaTitle,
72597             value: me.value,
72598             showToday: me.showToday,
72599             prevText: me.prevText,
72600             nextText: me.nextText,
72601             days: days
72602         });
72603         me.getTpl('renderTpl').longDayFormat = me.longDayFormat;
72604
72605         me.addChildEls('eventEl', 'prevEl', 'nextEl', 'middleBtnEl', 'footerEl');
72606
72607         this.callParent(arguments);
72608         me.el.unselectable();
72609
72610         me.cells = me.eventEl.select('tbody td');
72611         me.textNodes = me.eventEl.query('tbody td span');
72612
72613         me.monthBtn = Ext.create('Ext.button.Split', {
72614             text: '',
72615             tooltip: me.monthYearText,
72616             renderTo: me.middleBtnEl
72617         });
72618         
72619
72620
72621         me.todayBtn = Ext.create('Ext.button.Button', {
72622             renderTo: me.footerEl,
72623             text: Ext.String.format(me.todayText, today),
72624             tooltip: Ext.String.format(me.todayTip, today),
72625             handler: me.selectToday,
72626             scope: me
72627         });
72628     },
72629
72630     
72631     initEvents: function(){
72632         var me = this,
72633             eDate = Ext.Date,
72634             day = eDate.DAY;
72635
72636         this.callParent();
72637
72638         me.prevRepeater = Ext.create('Ext.util.ClickRepeater', me.prevEl, {
72639             handler: me.showPrevMonth,
72640             scope: me,
72641             preventDefault: true,
72642             stopDefault: true
72643         });
72644
72645         me.nextRepeater = Ext.create('Ext.util.ClickRepeater', me.nextEl, {
72646             handler: me.showNextMonth,
72647             scope: me,
72648             preventDefault:true,
72649             stopDefault:true
72650         });
72651
72652         me.keyNav = Ext.create('Ext.util.KeyNav', me.eventEl, Ext.apply({
72653             scope: me,
72654             'left' : function(e){
72655                 if(e.ctrlKey){
72656                     me.showPrevMonth();
72657                 }else{
72658                     me.update(eDate.add(me.activeDate, day, -1));
72659                 }
72660             },
72661
72662             'right' : function(e){
72663                 if(e.ctrlKey){
72664                     me.showNextMonth();
72665                 }else{
72666                     me.update(eDate.add(me.activeDate, day, 1));
72667                 }
72668             },
72669
72670             'up' : function(e){
72671                 if(e.ctrlKey){
72672                     me.showNextYear();
72673                 }else{
72674                     me.update(eDate.add(me.activeDate, day, -7));
72675                 }
72676             },
72677
72678             'down' : function(e){
72679                 if(e.ctrlKey){
72680                     me.showPrevYear();
72681                 }else{
72682                     me.update(eDate.add(me.activeDate, day, 7));
72683                 }
72684             },
72685             'pageUp' : me.showNextMonth,
72686             'pageDown' : me.showPrevMonth,
72687             'enter' : function(e){
72688                 e.stopPropagation();
72689                 return true;
72690             }
72691         }, me.keyNavConfig));
72692
72693         if(me.showToday){
72694             me.todayKeyListener = me.eventEl.addKeyListener(Ext.EventObject.SPACE, me.selectToday,  me);
72695         }
72696         me.mon(me.eventEl, 'mousewheel', me.handleMouseWheel, me);
72697         me.mon(me.eventEl, 'click', me.handleDateClick,  me, {delegate: 'a.' + me.baseCls + '-date'});
72698         me.mon(me.monthBtn, 'click', me.showMonthPicker, me);
72699         me.mon(me.monthBtn, 'arrowclick', me.showMonthPicker, me);
72700         me.update(me.value);
72701     },
72702
72703     
72704     initDisabledDays : function(){
72705         var me = this,
72706             dd = me.disabledDates,
72707             re = '(?:',
72708             len;
72709
72710         if(!me.disabledDatesRE && dd){
72711                 len = dd.length - 1;
72712
72713             Ext.each(dd, function(d, i){
72714                 re += Ext.isDate(d) ? '^' + Ext.String.escapeRegex(Ext.Date.dateFormat(d, me.format)) + '$' : dd[i];
72715                 if(i != len){
72716                     re += '|';
72717                 }
72718             }, me);
72719             me.disabledDatesRE = new RegExp(re + ')');
72720         }
72721     },
72722
72723     
72724     setDisabledDates : function(dd){
72725         var me = this;
72726
72727         if(Ext.isArray(dd)){
72728             me.disabledDates = dd;
72729             me.disabledDatesRE = null;
72730         }else{
72731             me.disabledDatesRE = dd;
72732         }
72733         me.initDisabledDays();
72734         me.update(me.value, true);
72735         return me;
72736     },
72737
72738     
72739     setDisabledDays : function(dd){
72740         this.disabledDays = dd;
72741         return this.update(this.value, true);
72742     },
72743
72744     
72745     setMinDate : function(dt){
72746         this.minDate = dt;
72747         return this.update(this.value, true);
72748     },
72749
72750     
72751     setMaxDate : function(dt){
72752         this.maxDate = dt;
72753         return this.update(this.value, true);
72754     },
72755
72756     
72757     setValue : function(value){
72758         this.value = Ext.Date.clearTime(value, true);
72759         return this.update(this.value);
72760     },
72761
72762     
72763     getValue : function(){
72764         return this.value;
72765     },
72766
72767     
72768     focus : function(){
72769         this.update(this.activeDate);
72770     },
72771
72772     
72773     onEnable: function(){
72774         this.callParent();
72775         this.setDisabledStatus(false);
72776         this.update(this.activeDate);
72777
72778     },
72779
72780     
72781     onDisable : function(){
72782         this.callParent();
72783         this.setDisabledStatus(true);
72784     },
72785
72786     
72787     setDisabledStatus : function(disabled){
72788         var me = this;
72789
72790         me.keyNav.setDisabled(disabled);
72791         me.prevRepeater.setDisabled(disabled);
72792         me.nextRepeater.setDisabled(disabled);
72793         if (me.showToday) {
72794             me.todayKeyListener.setDisabled(disabled);
72795             me.todayBtn.setDisabled(disabled);
72796         }
72797     },
72798
72799     
72800     getActive: function(){
72801         return this.activeDate || this.value;
72802     },
72803
72804     
72805     runAnimation: function(isHide){
72806         var picker = this.monthPicker,
72807             options = {
72808                 duration: 200,
72809                 callback: function(){
72810                     if (isHide) {
72811                         picker.hide();
72812                     } else {
72813                         picker.show();
72814                     }
72815                 }
72816             };
72817
72818         if (isHide) {
72819             picker.el.slideOut('t', options);
72820         } else {
72821             picker.el.slideIn('t', options);
72822         }
72823     },
72824
72825     
72826     hideMonthPicker : function(animate){
72827         var me = this,
72828             picker = me.monthPicker;
72829
72830         if (picker) {
72831             if (me.shouldAnimate(animate)) {
72832                 me.runAnimation(true);
72833             } else {
72834                 picker.hide();
72835             }
72836         }
72837         return me;
72838     },
72839
72840     
72841     showMonthPicker : function(animate){
72842         var me = this,
72843             picker;
72844         
72845         if (me.rendered && !me.disabled) {
72846             picker = me.createMonthPicker();
72847             picker.setValue(me.getActive());
72848             picker.setSize(me.getSize());
72849             picker.setPosition(-1, -1);
72850             if (me.shouldAnimate(animate)) {
72851                 me.runAnimation(false);
72852             } else {
72853                 picker.show();
72854             }
72855         }
72856         return me;
72857     },
72858     
72859     
72860     shouldAnimate: function(animate){
72861         return Ext.isDefined(animate) ? animate : !this.disableAnim;
72862     },
72863
72864     
72865     createMonthPicker: function(){
72866         var me = this,
72867             picker = me.monthPicker;
72868
72869         if (!picker) {
72870             me.monthPicker = picker = Ext.create('Ext.picker.Month', {
72871                 renderTo: me.el,
72872                 floating: true,
72873                 shadow: false,
72874                 small: me.showToday === false,
72875                 listeners: {
72876                     scope: me,
72877                     cancelclick: me.onCancelClick,
72878                     okclick: me.onOkClick,
72879                     yeardblclick: me.onOkClick,
72880                     monthdblclick: me.onOkClick
72881                 }
72882             });
72883             if (!me.disableAnim) {
72884                 
72885                 picker.el.setStyle('display', 'none');
72886             }
72887             me.on('beforehide', Ext.Function.bind(me.hideMonthPicker, me, [false]));
72888         }
72889         return picker;
72890     },
72891
72892     
72893     onOkClick: function(picker, value){
72894         var me = this,
72895             month = value[0],
72896             year = value[1],
72897             date = new Date(year, month, me.getActive().getDate());
72898
72899         if (date.getMonth() !== month) {
72900             
72901             date = new Date(year, month, 1).getLastDateOfMonth();
72902         }
72903         me.update(date);
72904         me.hideMonthPicker();
72905     },
72906
72907     
72908     onCancelClick: function(){
72909         this.hideMonthPicker();
72910     },
72911
72912     
72913     showPrevMonth : function(e){
72914         return this.update(Ext.Date.add(this.activeDate, Ext.Date.MONTH, -1));
72915     },
72916
72917     
72918     showNextMonth : function(e){
72919         return this.update(Ext.Date.add(this.activeDate, Ext.Date.MONTH, 1));
72920     },
72921
72922     
72923     showPrevYear : function(){
72924         this.update(Ext.Date.add(this.activeDate, Ext.Date.YEAR, -1));
72925     },
72926
72927     
72928     showNextYear : function(){
72929         this.update(Ext.Date.add(this.activeDate, Ext.Date.YEAR, 1));
72930     },
72931
72932     
72933     handleMouseWheel : function(e){
72934         e.stopEvent();
72935         if(!this.disabled){
72936             var delta = e.getWheelDelta();
72937             if(delta > 0){
72938                 this.showPrevMonth();
72939             } else if(delta < 0){
72940                 this.showNextMonth();
72941             }
72942         }
72943     },
72944
72945     
72946     handleDateClick : function(e, t){
72947         var me = this,
72948             handler = me.handler;
72949
72950         e.stopEvent();
72951         if(!me.disabled && t.dateValue && !Ext.fly(t.parentNode).hasCls(me.disabledCellCls)){
72952             me.cancelFocus = me.focusOnSelect === false;
72953             me.setValue(new Date(t.dateValue));
72954             delete me.cancelFocus;
72955             me.fireEvent('select', me, me.value);
72956             if (handler) {
72957                 handler.call(me.scope || me, me, me.value);
72958             }
72959             
72960             
72961             
72962             
72963             me.onSelect();
72964         }
72965     },
72966
72967     
72968     onSelect: function() {
72969         if (this.hideOnSelect) {
72970              this.hide();
72971          }
72972     },
72973
72974     
72975     selectToday : function(){
72976         var me = this,
72977             btn = me.todayBtn,
72978             handler = me.handler;
72979
72980         if(btn && !btn.disabled){
72981             me.setValue(Ext.Date.clearTime(new Date()));
72982             me.fireEvent('select', me, me.value);
72983             if (handler) {
72984                 handler.call(me.scope || me, me, me.value);
72985             }
72986             me.onSelect();
72987         }
72988         return me;
72989     },
72990
72991     
72992     selectedUpdate: function(date, active){
72993         var me = this,
72994             t = date.getTime(),
72995             cells = me.cells,
72996             cls = me.selectedCls;
72997
72998         cells.removeCls(cls);
72999         cells.each(function(c){
73000             if (c.dom.firstChild.dateValue == t) {
73001                 me.el.dom.setAttribute('aria-activedescendent', c.dom.id);
73002                 c.addCls(cls);
73003                 if(me.isVisible() && !me.cancelFocus){
73004                     Ext.fly(c.dom.firstChild).focus(50);
73005                 }
73006                 return false;
73007             }
73008         }, this);
73009     },
73010
73011     
73012     fullUpdate: function(date, active){
73013         var me = this,
73014             cells = me.cells.elements,
73015             textNodes = me.textNodes,
73016             disabledCls = me.disabledCellCls,
73017             eDate = Ext.Date,
73018             i = 0,
73019             extraDays = 0,
73020             visible = me.isVisible(),
73021             sel = +eDate.clearTime(date, true),
73022             today = +eDate.clearTime(new Date()),
73023             min = me.minDate ? eDate.clearTime(me.minDate, true) : Number.NEGATIVE_INFINITY,
73024             max = me.maxDate ? eDate.clearTime(me.maxDate, true) : Number.POSITIVE_INFINITY,
73025             ddMatch = me.disabledDatesRE,
73026             ddText = me.disabledDatesText,
73027             ddays = me.disabledDays ? me.disabledDays.join('') : false,
73028             ddaysText = me.disabledDaysText,
73029             format = me.format,
73030             days = eDate.getDaysInMonth(date),
73031             firstOfMonth = eDate.getFirstDateOfMonth(date),
73032             startingPos = firstOfMonth.getDay() - me.startDay,
73033             previousMonth = eDate.add(date, eDate.MONTH, -1),
73034             longDayFormat = me.longDayFormat,
73035             prevStart,
73036             current,
73037             disableToday,
73038             tempDate,
73039             setCellClass,
73040             html,
73041             cls,
73042             formatValue,
73043             value;
73044
73045         if (startingPos < 0) {
73046             startingPos += 7;
73047         }
73048
73049         days += startingPos;
73050         prevStart = eDate.getDaysInMonth(previousMonth) - startingPos;
73051         current = new Date(previousMonth.getFullYear(), previousMonth.getMonth(), prevStart, me.initHour);
73052
73053         if (me.showToday) {
73054             tempDate = eDate.clearTime(new Date());
73055             disableToday = (tempDate < min || tempDate > max ||
73056                 (ddMatch && format && ddMatch.test(eDate.dateFormat(tempDate, format))) ||
73057                 (ddays && ddays.indexOf(tempDate.getDay()) != -1));
73058
73059             if (!me.disabled) {
73060                 me.todayBtn.setDisabled(disableToday);
73061                 me.todayKeyListener.setDisabled(disableToday);
73062             }
73063         }
73064
73065         setCellClass = function(cell){
73066             value = +eDate.clearTime(current, true);
73067             cell.title = eDate.format(current, longDayFormat);
73068             
73069             cell.firstChild.dateValue = value;
73070             if(value == today){
73071                 cell.className += ' ' + me.todayCls;
73072                 cell.title = me.todayText;
73073             }
73074             if(value == sel){
73075                 cell.className += ' ' + me.selectedCls;
73076                 me.el.dom.setAttribute('aria-activedescendant', cell.id);
73077                 if (visible && me.floating) {
73078                     Ext.fly(cell.firstChild).focus(50);
73079                 }
73080             }
73081             
73082             if(value < min) {
73083                 cell.className = disabledCls;
73084                 cell.title = me.minText;
73085                 return;
73086             }
73087             if(value > max) {
73088                 cell.className = disabledCls;
73089                 cell.title = me.maxText;
73090                 return;
73091             }
73092             if(ddays){
73093                 if(ddays.indexOf(current.getDay()) != -1){
73094                     cell.title = ddaysText;
73095                     cell.className = disabledCls;
73096                 }
73097             }
73098             if(ddMatch && format){
73099                 formatValue = eDate.dateFormat(current, format);
73100                 if(ddMatch.test(formatValue)){
73101                     cell.title = ddText.replace('%0', formatValue);
73102                     cell.className = disabledCls;
73103                 }
73104             }
73105         };
73106
73107         for(; i < me.numDays; ++i) {
73108             if (i < startingPos) {
73109                 html = (++prevStart);
73110                 cls = me.prevCls;
73111             } else if (i >= days) {
73112                 html = (++extraDays);
73113                 cls = me.nextCls;
73114             } else {
73115                 html = i - startingPos + 1;
73116                 cls = me.activeCls;
73117             }
73118             textNodes[i].innerHTML = html;
73119             cells[i].className = cls;
73120             current.setDate(current.getDate() + 1);
73121             setCellClass(cells[i]);
73122         }
73123
73124         me.monthBtn.setText(me.monthNames[date.getMonth()] + ' ' + date.getFullYear());
73125     },
73126
73127     
73128     update : function(date, forceRefresh){
73129         var me = this,
73130             active = me.activeDate;
73131
73132         if (me.rendered) {
73133             me.activeDate = date;
73134             if(!forceRefresh && active && me.el && active.getMonth() == date.getMonth() && active.getFullYear() == date.getFullYear()){
73135                 me.selectedUpdate(date, active);
73136             } else {
73137                 me.fullUpdate(date, active);
73138             }
73139         }
73140         return me;
73141     },
73142
73143     
73144     beforeDestroy : function() {
73145         var me = this;
73146
73147         if (me.rendered) {
73148             Ext.destroy(
73149                 me.todayKeyListener,
73150                 me.keyNav,
73151                 me.monthPicker,
73152                 me.monthBtn,
73153                 me.nextRepeater,
73154                 me.prevRepeater,
73155                 me.todayBtn
73156             );
73157             delete me.textNodes;
73158             delete me.cells.elements;
73159         }
73160         me.callParent();
73161     },
73162
73163     
73164     onShow: function() {
73165         this.callParent(arguments);
73166         if (this.focusOnShow) {
73167             this.focus();
73168         }
73169     }
73170 },
73171
73172
73173 function() {
73174     var proto = this.prototype;
73175
73176     proto.monthNames = Ext.Date.monthNames;
73177
73178     proto.dayNames = Ext.Date.dayNames;
73179
73180     proto.format = Ext.Date.defaultFormat;
73181 });
73182
73183
73184 Ext.define('Ext.form.field.Date', {
73185     extend:'Ext.form.field.Picker',
73186     alias: 'widget.datefield',
73187     requires: ['Ext.picker.Date'],
73188     alternateClassName: ['Ext.form.DateField', 'Ext.form.Date'],
73189
73190     
73191     format : "m/d/Y",
73192     
73193     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",
73194     
73195     disabledDaysText : "Disabled",
73196     
73197     disabledDatesText : "Disabled",
73198     
73199     minText : "The date in this field must be equal to or after {0}",
73200     
73201     maxText : "The date in this field must be equal to or before {0}",
73202     
73203     invalidText : "{0} is not a valid date - it must be in the format {1}",
73204     
73205     triggerCls : Ext.baseCSSPrefix + 'form-date-trigger',
73206     
73207     showToday : true,
73208     
73209     
73210     
73211     
73212
73213     
73214
73215     
73216     
73217     initTime: '12', 
73218
73219     initTimeFormat: 'H',
73220
73221     matchFieldWidth: false,
73222     
73223     startDay: 0,
73224
73225     initComponent : function(){
73226         var me = this,
73227             isString = Ext.isString,
73228             min, max;
73229
73230         min = me.minValue;
73231         max = me.maxValue;
73232         if(isString(min)){
73233             me.minValue = me.parseDate(min);
73234         }
73235         if(isString(max)){
73236             me.maxValue = me.parseDate(max);
73237         }
73238         me.disabledDatesRE = null;
73239         me.initDisabledDays();
73240
73241         me.callParent();
73242     },
73243
73244     initValue: function() {
73245         var me = this,
73246             value = me.value;
73247
73248         
73249         if (Ext.isString(value)) {
73250             me.value = me.rawToValue(value);
73251         }
73252
73253         me.callParent();
73254     },
73255
73256     
73257     initDisabledDays : function(){
73258         if(this.disabledDates){
73259             var dd = this.disabledDates,
73260                 len = dd.length - 1,
73261                 re = "(?:";
73262
73263             Ext.each(dd, function(d, i){
73264                 re += Ext.isDate(d) ? '^' + Ext.String.escapeRegex(d.dateFormat(this.format)) + '$' : dd[i];
73265                 if (i !== len) {
73266                     re += '|';
73267                 }
73268             }, this);
73269             this.disabledDatesRE = new RegExp(re + ')');
73270         }
73271     },
73272
73273     
73274     setDisabledDates : function(dd){
73275         var me = this,
73276             picker = me.picker;
73277
73278         me.disabledDates = dd;
73279         me.initDisabledDays();
73280         if (picker) {
73281             picker.setDisabledDates(me.disabledDatesRE);
73282         }
73283     },
73284
73285     
73286     setDisabledDays : function(dd){
73287         var picker = this.picker;
73288
73289         this.disabledDays = dd;
73290         if (picker) {
73291             picker.setDisabledDays(dd);
73292         }
73293     },
73294
73295     
73296     setMinValue : function(dt){
73297         var me = this,
73298             picker = me.picker,
73299             minValue = (Ext.isString(dt) ? me.parseDate(dt) : dt);
73300
73301         me.minValue = minValue;
73302         if (picker) {
73303             picker.minText = Ext.String.format(me.minText, me.formatDate(me.minValue));
73304             picker.setMinDate(minValue);
73305         }
73306     },
73307
73308     
73309     setMaxValue : function(dt){
73310         var me = this,
73311             picker = me.picker,
73312             maxValue = (Ext.isString(dt) ? me.parseDate(dt) : dt);
73313
73314         me.maxValue = maxValue;
73315         if (picker) {
73316             picker.maxText = Ext.String.format(me.maxText, me.formatDate(me.maxValue));
73317             picker.setMaxDate(maxValue);
73318         }
73319     },
73320
73321     
73322     getErrors: function(value) {
73323         var me = this,
73324             format = Ext.String.format,
73325             clearTime = Ext.Date.clearTime,
73326             errors = me.callParent(arguments),
73327             disabledDays = me.disabledDays,
73328             disabledDatesRE = me.disabledDatesRE,
73329             minValue = me.minValue,
73330             maxValue = me.maxValue,
73331             len = disabledDays ? disabledDays.length : 0,
73332             i = 0,
73333             svalue,
73334             fvalue,
73335             day,
73336             time;
73337
73338         value = me.formatDate(value || me.processRawValue(me.getRawValue()));
73339
73340         if (value === null || value.length < 1) { 
73341              return errors;
73342         }
73343
73344         svalue = value;
73345         value = me.parseDate(value);
73346         if (!value) {
73347             errors.push(format(me.invalidText, svalue, me.format));
73348             return errors;
73349         }
73350
73351         time = value.getTime();
73352         if (minValue && time < clearTime(minValue).getTime()) {
73353             errors.push(format(me.minText, me.formatDate(minValue)));
73354         }
73355
73356         if (maxValue && time > clearTime(maxValue).getTime()) {
73357             errors.push(format(me.maxText, me.formatDate(maxValue)));
73358         }
73359
73360         if (disabledDays) {
73361             day = value.getDay();
73362
73363             for(; i < len; i++) {
73364                 if (day === disabledDays[i]) {
73365                     errors.push(me.disabledDaysText);
73366                     break;
73367                 }
73368             }
73369         }
73370
73371         fvalue = me.formatDate(value);
73372         if (disabledDatesRE && disabledDatesRE.test(fvalue)) {
73373             errors.push(format(me.disabledDatesText, fvalue));
73374         }
73375
73376         return errors;
73377     },
73378
73379     rawToValue: function(rawValue) {
73380         return this.parseDate(rawValue) || rawValue || null;
73381     },
73382
73383     valueToRaw: function(value) {
73384         return this.formatDate(this.parseDate(value));
73385     },
73386
73387     
73388
73389     
73390     safeParse : function(value, format) {
73391         var me = this,
73392             utilDate = Ext.Date,
73393             parsedDate,
73394             result = null;
73395
73396         if (utilDate.formatContainsHourInfo(format)) {
73397             
73398             result = utilDate.parse(value, format);
73399         } else {
73400             
73401             parsedDate = utilDate.parse(value + ' ' + me.initTime, format + ' ' + me.initTimeFormat);
73402             if (parsedDate) {
73403                 result = utilDate.clearTime(parsedDate);
73404             }
73405         }
73406         return result;
73407     },
73408
73409     
73410     getSubmitValue: function() {
73411         var format = this.submitFormat || this.format,
73412             value = this.getValue();
73413
73414         return value ? Ext.Date.format(value, format) : '';
73415     },
73416
73417     
73418     parseDate : function(value) {
73419         if(!value || Ext.isDate(value)){
73420             return value;
73421         }
73422
73423         var me = this,
73424             val = me.safeParse(value, me.format),
73425             altFormats = me.altFormats,
73426             altFormatsArray = me.altFormatsArray,
73427             i = 0,
73428             len;
73429
73430         if (!val && altFormats) {
73431             altFormatsArray = altFormatsArray || altFormats.split('|');
73432             len = altFormatsArray.length;
73433             for (; i < len && !val; ++i) {
73434                 val = me.safeParse(value, altFormatsArray[i]);
73435             }
73436         }
73437         return val;
73438     },
73439
73440     
73441     formatDate : function(date){
73442         return Ext.isDate(date) ? Ext.Date.dateFormat(date, this.format) : date;
73443     },
73444
73445     createPicker: function() {
73446         var me = this,
73447             format = Ext.String.format;
73448
73449         return Ext.create('Ext.picker.Date', {
73450             pickerField: me,
73451             ownerCt: me.ownerCt,
73452             renderTo: document.body,
73453             floating: true,
73454             hidden: true,
73455             focusOnShow: true,
73456             minDate: me.minValue,
73457             maxDate: me.maxValue,
73458             disabledDatesRE: me.disabledDatesRE,
73459             disabledDatesText: me.disabledDatesText,
73460             disabledDays: me.disabledDays,
73461             disabledDaysText: me.disabledDaysText,
73462             format: me.format,
73463             showToday: me.showToday,
73464             startDay: me.startDay,
73465             minText: format(me.minText, me.formatDate(me.minValue)),
73466             maxText: format(me.maxText, me.formatDate(me.maxValue)),
73467             listeners: {
73468                 scope: me,
73469                 select: me.onSelect
73470             },
73471             keyNavConfig: {
73472                 esc: function() {
73473                     me.collapse();
73474                 }
73475             }
73476         });
73477     },
73478
73479     onSelect: function(m, d) {
73480         var me = this;
73481
73482         me.setValue(d);
73483         me.fireEvent('select', me, d);
73484         me.collapse();
73485     },
73486
73487     
73488     onExpand: function() {
73489         var value = this.getValue();
73490         this.picker.setValue(Ext.isDate(value) ? value : new Date());
73491     },
73492
73493     
73494     onCollapse: function() {
73495         this.focus(false, 60);
73496     },
73497
73498     
73499     beforeBlur : function(){
73500         var me = this,
73501             v = me.parseDate(me.getRawValue()),
73502             focusTask = me.focusTask;
73503
73504         if (focusTask) {
73505             focusTask.cancel();
73506         }
73507
73508         if (v) {
73509             me.setValue(v);
73510         }
73511     }
73512
73513     
73514     
73515     
73516     
73517 });
73518
73519
73520 Ext.define('Ext.form.field.Display', {
73521     extend:'Ext.form.field.Base',
73522     alias: 'widget.displayfield',
73523     requires: ['Ext.util.Format', 'Ext.XTemplate'],
73524     alternateClassName: ['Ext.form.DisplayField', 'Ext.form.Display'],
73525     fieldSubTpl: [
73526         '<div id="{id}" class="{fieldCls}"></div>',
73527         {
73528             compiled: true,
73529             disableFormats: true
73530         }
73531     ],
73532
73533     
73534     fieldCls: Ext.baseCSSPrefix + 'form-display-field',
73535
73536     
73537     htmlEncode: false,
73538
73539     validateOnChange: false,
73540
73541     initEvents: Ext.emptyFn,
73542
73543     submitValue: false,
73544
73545     isValid: function() {
73546         return true;
73547     },
73548
73549     validate: function() {
73550         return true;
73551     },
73552
73553     getRawValue: function() {
73554         return this.rawValue;
73555     },
73556
73557     setRawValue: function(value) {
73558         var me = this;
73559         value = Ext.value(value, '');
73560         me.rawValue = value;
73561         if (me.rendered) {
73562             me.inputEl.dom.innerHTML = me.htmlEncode ? Ext.util.Format.htmlEncode(value) : value;
73563         }
73564         return value;
73565     },
73566
73567     
73568     getContentTarget: function() {
73569         return this.inputEl;
73570     }
73571
73572     
73573     
73574     
73575     
73576     
73577     
73578 });
73579
73580
73581 Ext.define("Ext.form.field.File", {
73582     extend: 'Ext.form.field.Text',
73583     alias: ['widget.filefield', 'widget.fileuploadfield'],
73584     alternateClassName: ['Ext.form.FileUploadField', 'Ext.ux.form.FileUploadField', 'Ext.form.File'],
73585     uses: ['Ext.button.Button', 'Ext.layout.component.field.File'],
73586
73587     
73588     buttonText: 'Browse...',
73589
73590     
73591     buttonOnly: false,
73592
73593     
73594     buttonMargin: 3,
73595
73596     
73597
73598     
73599
73600     
73601
73602     
73603
73604     
73605     fieldBodyCls: Ext.baseCSSPrefix + 'form-file-wrap',
73606
73607     
73608     readOnly: true,
73609
73610     
73611     componentLayout: 'filefield',
73612
73613     
73614     onRender: function() {
73615         var me = this,
73616             inputEl;
73617
73618         me.callParent(arguments);
73619
73620         me.createButton();
73621         me.createFileInput();
73622         
73623         
73624         
73625         if (me.disabled) {
73626             me.disableItems();
73627         }
73628
73629         inputEl = me.inputEl;
73630         inputEl.dom.removeAttribute('name'); 
73631         if (me.buttonOnly) {
73632             inputEl.setDisplayed(false);
73633         }
73634     },
73635
73636     
73637     createButton: function() {
73638         var me = this;
73639         me.button = Ext.widget('button', Ext.apply({
73640             ui: me.ui,
73641             renderTo: me.bodyEl,
73642             text: me.buttonText,
73643             cls: Ext.baseCSSPrefix + 'form-file-btn',
73644             preventDefault: false,
73645             style: me.buttonOnly ? '' : 'margin-left:' + me.buttonMargin + 'px'
73646         }, me.buttonConfig));
73647     },
73648
73649     
73650     createFileInput : function() {
73651         var me = this;
73652         me.fileInputEl = me.button.el.createChild({
73653             name: me.getName(),
73654             cls: Ext.baseCSSPrefix + 'form-file-input',
73655             tag: 'input',
73656             type: 'file',
73657             size: 1
73658         }).on('change', me.onFileChange, me);
73659     },
73660
73661     
73662     onFileChange: function() {
73663         this.lastValue = null; 
73664         Ext.form.field.File.superclass.setValue.call(this, this.fileInputEl.dom.value);
73665     },
73666
73667     
73668     setValue: Ext.emptyFn,
73669
73670     reset : function(){
73671         var me = this;
73672         if (me.rendered) {
73673             me.fileInputEl.remove();
73674             me.createFileInput();
73675             me.inputEl.dom.value = '';
73676         }
73677         me.callParent();
73678     },
73679
73680     onDisable: function(){
73681         this.callParent();
73682         this.disableItems();
73683     },
73684     
73685     disableItems: function(){
73686         var file = this.fileInputEl,
73687             button = this.button;
73688              
73689         if (file) {
73690             file.dom.disabled = true;
73691         }
73692         if (button) {
73693             button.disable();
73694         }    
73695     },
73696
73697     onEnable: function(){
73698         var me = this;
73699         me.callParent();
73700         me.fileInputEl.dom.disabled = false;
73701         me.button.enable();
73702     },
73703
73704     isFileUpload: function() {
73705         return true;
73706     },
73707
73708     extractFileInput: function() {
73709         var fileInput = this.fileInputEl.dom;
73710         this.reset();
73711         return fileInput;
73712     },
73713
73714     onDestroy: function(){
73715         Ext.destroyMembers(this, 'fileInputEl', 'button');
73716         this.callParent();
73717     }
73718
73719
73720 });
73721
73722
73723 Ext.define('Ext.form.field.Hidden', {
73724     extend:'Ext.form.field.Base',
73725     alias: ['widget.hiddenfield', 'widget.hidden'],
73726     alternateClassName: 'Ext.form.Hidden',
73727
73728     
73729     inputType : 'hidden',
73730     hideLabel: true,
73731     
73732     initComponent: function(){
73733         this.formItemCls += '-hidden';
73734         this.callParent();    
73735     },
73736     
73737     
73738     isEqual: function(value1, value2) {
73739         return this.isEqualAsString(value1, value2);
73740     },
73741
73742     
73743     initEvents: Ext.emptyFn,
73744     setSize : Ext.emptyFn,
73745     setWidth : Ext.emptyFn,
73746     setHeight : Ext.emptyFn,
73747     setPosition : Ext.emptyFn,
73748     setPagePosition : Ext.emptyFn,
73749     markInvalid : Ext.emptyFn,
73750     clearInvalid : Ext.emptyFn
73751 });
73752
73753
73754 Ext.define('Ext.picker.Color', {
73755     extend: 'Ext.Component',
73756     requires: 'Ext.XTemplate',
73757     alias: 'widget.colorpicker',
73758     alternateClassName: 'Ext.ColorPalette',
73759
73760     
73761     componentCls : Ext.baseCSSPrefix + 'color-picker',
73762
73763     
73764     selectedCls: Ext.baseCSSPrefix + 'color-picker-selected',
73765
73766     
73767     value : null,
73768
73769     
73770     clickEvent :'click',
73771
73772     
73773     allowReselect : false,
73774
73775     
73776     colors : [
73777         '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
73778         '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
73779         'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
73780         'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
73781         'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
73782     ],
73783
73784     
73785
73786     
73787
73788     colorRe: /(?:^|\s)color-(.{6})(?:\s|$)/,
73789     
73790     renderTpl: [
73791         '<tpl for="colors">',
73792             '<a href="#" class="color-{.}" hidefocus="on">',
73793                 '<em><span style="background:#{.}" unselectable="on">&#160;</span></em>',
73794             '</a>',
73795         '</tpl>'
73796     ],
73797
73798     
73799     initComponent : function(){
73800         var me = this;
73801
73802         me.callParent(arguments);
73803         me.addEvents(
73804             
73805             'select'
73806         );
73807
73808         if (me.handler) {
73809             me.on('select', me.handler, me.scope, true);
73810         }
73811     },
73812
73813
73814     
73815     onRender : function(container, position){
73816         var me = this,
73817             clickEvent = me.clickEvent;
73818
73819         Ext.apply(me.renderData, {
73820             itemCls: me.itemCls,
73821             colors: me.colors
73822         });
73823         me.callParent(arguments);
73824
73825         me.mon(me.el, clickEvent, me.handleClick, me, {delegate: 'a'});
73826         
73827         if(clickEvent != 'click'){
73828             me.mon(me.el, 'click', Ext.emptyFn, me, {delegate: 'a', stopEvent: true});
73829         }
73830     },
73831
73832     
73833     afterRender : function(){
73834         var me = this,
73835             value;
73836
73837         me.callParent(arguments);
73838         if (me.value) {
73839             value = me.value;
73840             me.value = null;
73841             me.select(value, true);
73842         }
73843     },
73844
73845     
73846     handleClick : function(event, target){
73847         var me = this,
73848             color;
73849
73850         event.stopEvent();
73851         if (!me.disabled) {
73852             color = target.className.match(me.colorRe)[1];
73853             me.select(color.toUpperCase());
73854         }
73855     },
73856
73857     
73858     select : function(color, suppressEvent){
73859
73860         var me = this,
73861             selectedCls = me.selectedCls,
73862             value = me.value,
73863             el;
73864
73865         color = color.replace('#', '');
73866         if (!me.rendered) {
73867             me.value = color;
73868             return;
73869         }
73870
73871
73872         if (color != value || me.allowReselect) {
73873             el = me.el;
73874
73875             if (me.value) {
73876                 el.down('a.color-' + value).removeCls(selectedCls);
73877             }
73878             el.down('a.color-' + color).addCls(selectedCls);
73879             me.value = color;
73880             if (suppressEvent !== true) {
73881                 me.fireEvent('select', me, color);
73882             }
73883         }
73884     },
73885
73886     
73887     getValue: function(){
73888         return this.value || null;
73889     }
73890 });
73891
73892
73893
73894 Ext.define('Ext.layout.component.field.HtmlEditor', {
73895     extend: 'Ext.layout.component.field.Field',
73896     alias: ['layout.htmleditor'],
73897
73898     type: 'htmleditor',
73899
73900     sizeBodyContents: function(width, height) {
73901         var me = this,
73902             owner = me.owner,
73903             bodyEl = owner.bodyEl,
73904             toolbar = owner.getToolbar(),
73905             textarea = owner.textareaEl,
73906             iframe = owner.iframeEl,
73907             editorHeight;
73908
73909         if (Ext.isNumber(width)) {
73910             width -= bodyEl.getFrameWidth('lr');
73911         }
73912         toolbar.setWidth(width);
73913         textarea.setWidth(width);
73914         iframe.setWidth(width);
73915
73916         
73917         if (Ext.isNumber(height)) {
73918             editorHeight = height - toolbar.getHeight() - bodyEl.getFrameWidth('tb');
73919             textarea.setHeight(editorHeight);
73920             iframe.setHeight(editorHeight);
73921         }
73922     }
73923 });
73924
73925 Ext.define('Ext.form.field.HtmlEditor', {
73926     extend:'Ext.Component',
73927     mixins: {
73928         labelable: 'Ext.form.Labelable',
73929         field: 'Ext.form.field.Field'
73930     },
73931     alias: 'widget.htmleditor',
73932     alternateClassName: 'Ext.form.HtmlEditor',
73933     requires: [
73934         'Ext.tip.QuickTipManager',
73935         'Ext.picker.Color',
73936         'Ext.toolbar.Item',
73937         'Ext.toolbar.Toolbar',
73938         'Ext.util.Format',
73939         'Ext.layout.component.field.HtmlEditor'
73940     ],
73941
73942     fieldSubTpl: [
73943         '<div id="{cmpId}-toolbarWrap" class="{toolbarWrapCls}"></div>',
73944         '<textarea id="{cmpId}-textareaEl" name="{name}" tabIndex="-1" class="{textareaCls}" ',
73945             'style="{size}" autocomplete="off"></textarea>',
73946         '<iframe id="{cmpId}-iframeEl" name="{iframeName}" frameBorder="0" style="overflow:auto;{size}" src="{iframeSrc}"></iframe>',
73947         {
73948             compiled: true,
73949             disableFormats: true
73950         }
73951     ],
73952
73953     
73954     enableFormat : true,
73955     
73956     enableFontSize : true,
73957     
73958     enableColors : true,
73959     
73960     enableAlignments : true,
73961     
73962     enableLists : true,
73963     
73964     enableSourceEdit : true,
73965     
73966     enableLinks : true,
73967     
73968     enableFont : true,
73969     
73970     createLinkText : 'Please enter the URL for the link:',
73971     
73972     defaultLinkValue : 'http:/'+'/',
73973     
73974     fontFamilies : [
73975         'Arial',
73976         'Courier New',
73977         'Tahoma',
73978         'Times New Roman',
73979         'Verdana'
73980     ],
73981     defaultFont: 'tahoma',
73982     
73983     defaultValue: (Ext.isOpera || Ext.isIE6) ? '&#160;' : '&#8203;',
73984
73985     fieldBodyCls: Ext.baseCSSPrefix + 'html-editor-wrap',
73986
73987     componentLayout: 'htmleditor',
73988
73989     
73990     initialized : false,
73991     activated : false,
73992     sourceEditMode : false,
73993     iframePad:3,
73994     hideMode:'offsets',
73995
73996     maskOnDisable: true,
73997
73998     
73999     initComponent : function(){
74000         var me = this;
74001
74002         me.addEvents(
74003             
74004             'initialize',
74005             
74006             'activate',
74007              
74008             'beforesync',
74009              
74010             'beforepush',
74011              
74012             'sync',
74013              
74014             'push',
74015              
74016             'editmodechange'
74017         );
74018
74019         me.callParent(arguments);
74020
74021         
74022         me.initLabelable();
74023         me.initField();
74024     },
74025
74026     
74027     createToolbar : function(editor){
74028         var me = this,
74029             items = [],
74030             tipsEnabled = Ext.tip.QuickTipManager && Ext.tip.QuickTipManager.isEnabled(),
74031             baseCSSPrefix = Ext.baseCSSPrefix,
74032             fontSelectItem, toolbar, undef;
74033
74034         function btn(id, toggle, handler){
74035             return {
74036                 itemId : id,
74037                 cls : baseCSSPrefix + 'btn-icon',
74038                 iconCls: baseCSSPrefix + 'edit-'+id,
74039                 enableToggle:toggle !== false,
74040                 scope: editor,
74041                 handler:handler||editor.relayBtnCmd,
74042                 clickEvent:'mousedown',
74043                 tooltip: tipsEnabled ? editor.buttonTips[id] || undef : undef,
74044                 overflowText: editor.buttonTips[id].title || undef,
74045                 tabIndex:-1
74046             };
74047         }
74048
74049
74050         if (me.enableFont && !Ext.isSafari2) {
74051             fontSelectItem = Ext.widget('component', {
74052                 renderTpl: [
74053                     '<select id="{id}-selectEl" class="{cls}">',
74054                         '<tpl for="fonts">',
74055                             '<option value="{[values.toLowerCase()]}" style="font-family:{.}"<tpl if="values.toLowerCase()==parent.defaultFont"> selected</tpl>>{.}</option>',
74056                         '</tpl>',
74057                     '</select>'
74058                 ],
74059                 renderData: {
74060                     cls: baseCSSPrefix + 'font-select',
74061                     fonts: me.fontFamilies,
74062                     defaultFont: me.defaultFont
74063                 },
74064                 childEls: ['selectEl'],
74065                 onDisable: function() {
74066                     var selectEl = this.selectEl;
74067                     if (selectEl) {
74068                         selectEl.dom.disabled = true;
74069                     }
74070                     Ext.Component.superclass.onDisable.apply(this, arguments);
74071                 },
74072                 onEnable: function() {
74073                     var selectEl = this.selectEl;
74074                     if (selectEl) {
74075                         selectEl.dom.disabled = false;
74076                     }
74077                     Ext.Component.superclass.onEnable.apply(this, arguments);
74078                 }
74079             });
74080
74081             items.push(
74082                 fontSelectItem,
74083                 '-'
74084             );
74085         }
74086
74087         if (me.enableFormat) {
74088             items.push(
74089                 btn('bold'),
74090                 btn('italic'),
74091                 btn('underline')
74092             );
74093         }
74094
74095         if (me.enableFontSize) {
74096             items.push(
74097                 '-',
74098                 btn('increasefontsize', false, me.adjustFont),
74099                 btn('decreasefontsize', false, me.adjustFont)
74100             );
74101         }
74102
74103         if (me.enableColors) {
74104             items.push(
74105                 '-', {
74106                     itemId: 'forecolor',
74107                     cls: baseCSSPrefix + 'btn-icon',
74108                     iconCls: baseCSSPrefix + 'edit-forecolor',
74109                     overflowText: editor.buttonTips.forecolor.title,
74110                     tooltip: tipsEnabled ? editor.buttonTips.forecolor || undef : undef,
74111                     tabIndex:-1,
74112                     menu : Ext.widget('menu', {
74113                         plain: true,
74114                         items: [{
74115                             xtype: 'colorpicker',
74116                             allowReselect: true,
74117                             focus: Ext.emptyFn,
74118                             value: '000000',
74119                             plain: true,
74120                             clickEvent: 'mousedown',
74121                             handler: function(cp, color) {
74122                                 me.execCmd('forecolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
74123                                 me.deferFocus();
74124                                 this.up('menu').hide();
74125                             }
74126                         }]
74127                     })
74128                 }, {
74129                     itemId: 'backcolor',
74130                     cls: baseCSSPrefix + 'btn-icon',
74131                     iconCls: baseCSSPrefix + 'edit-backcolor',
74132                     overflowText: editor.buttonTips.backcolor.title,
74133                     tooltip: tipsEnabled ? editor.buttonTips.backcolor || undef : undef,
74134                     tabIndex:-1,
74135                     menu : Ext.widget('menu', {
74136                         plain: true,
74137                         items: [{
74138                             xtype: 'colorpicker',
74139                             focus: Ext.emptyFn,
74140                             value: 'FFFFFF',
74141                             plain: true,
74142                             allowReselect: true,
74143                             clickEvent: 'mousedown',
74144                             handler: function(cp, color) {
74145                                 if (Ext.isGecko) {
74146                                     me.execCmd('useCSS', false);
74147                                     me.execCmd('hilitecolor', color);
74148                                     me.execCmd('useCSS', true);
74149                                     me.deferFocus();
74150                                 } else {
74151                                     me.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
74152                                     me.deferFocus();
74153                                 }
74154                                 this.up('menu').hide();
74155                             }
74156                         }]
74157                     })
74158                 }
74159             );
74160         }
74161
74162         if (me.enableAlignments) {
74163             items.push(
74164                 '-',
74165                 btn('justifyleft'),
74166                 btn('justifycenter'),
74167                 btn('justifyright')
74168             );
74169         }
74170
74171         if (!Ext.isSafari2) {
74172             if (me.enableLinks) {
74173                 items.push(
74174                     '-',
74175                     btn('createlink', false, me.createLink)
74176                 );
74177             }
74178
74179             if (me.enableLists) {
74180                 items.push(
74181                     '-',
74182                     btn('insertorderedlist'),
74183                     btn('insertunorderedlist')
74184                 );
74185             }
74186             if (me.enableSourceEdit) {
74187                 items.push(
74188                     '-',
74189                     btn('sourceedit', true, function(btn){
74190                         me.toggleSourceEdit(!me.sourceEditMode);
74191                     })
74192                 );
74193             }
74194         }
74195
74196         
74197         toolbar = Ext.widget('toolbar', {
74198             renderTo: me.toolbarWrap,
74199             enableOverflow: true,
74200             items: items
74201         });
74202
74203         if (fontSelectItem) {
74204             me.fontSelect = fontSelectItem.selectEl;
74205
74206             me.mon(me.fontSelect, 'change', function(){
74207                 me.relayCmd('fontname', me.fontSelect.dom.value);
74208                 me.deferFocus();
74209             });
74210         }
74211
74212         
74213         me.mon(toolbar.el, 'click', function(e){
74214             e.preventDefault();
74215         });
74216
74217         me.toolbar = toolbar;
74218     },
74219
74220     onDisable: function() {
74221         this.bodyEl.mask();
74222         this.callParent(arguments);
74223     },
74224
74225     onEnable: function() {
74226         this.bodyEl.unmask();
74227         this.callParent(arguments);
74228     },
74229
74230     
74231     setReadOnly: function(readOnly) {
74232         var me = this,
74233             textareaEl = me.textareaEl,
74234             iframeEl = me.iframeEl,
74235             body;
74236
74237         me.readOnly = readOnly;
74238
74239         if (textareaEl) {
74240             textareaEl.dom.readOnly = readOnly;
74241         }
74242
74243         if (me.initialized) {
74244             body = me.getEditorBody();
74245             if (Ext.isIE) {
74246                 
74247                 iframeEl.setDisplayed(false);
74248                 body.contentEditable = !readOnly;
74249                 iframeEl.setDisplayed(true);
74250             } else {
74251                 me.setDesignMode(!readOnly);
74252             }
74253             if (body) {
74254                 body.style.cursor = readOnly ? 'default' : 'text';
74255             }
74256             me.disableItems(readOnly);
74257         }
74258     },
74259
74260     
74261     getDocMarkup: function() {
74262         var me = this,
74263             h = me.iframeEl.getHeight() - me.iframePad * 2;
74264         return Ext.String.format('<html><head><style type="text/css">body{border:0;margin:0;padding:{0}px;height:{1}px;box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box;cursor:text}</style></head><body></body></html>', me.iframePad, h);
74265     },
74266
74267     
74268     getEditorBody: function() {
74269         var doc = this.getDoc();
74270         return doc.body || doc.documentElement;
74271     },
74272
74273     
74274     getDoc: function() {
74275         return (!Ext.isIE && this.iframeEl.dom.contentDocument) || this.getWin().document;
74276     },
74277
74278     
74279     getWin: function() {
74280         return Ext.isIE ? this.iframeEl.dom.contentWindow : window.frames[this.iframeEl.dom.name];
74281     },
74282
74283     
74284     onRender: function() {
74285         var me = this;
74286
74287         me.onLabelableRender();
74288
74289         me.addChildEls('toolbarWrap', 'iframeEl', 'textareaEl');
74290
74291         me.callParent(arguments);
74292
74293         me.textareaEl.dom.value = me.value || '';
74294
74295         
74296         me.monitorTask = Ext.TaskManager.start({
74297             run: me.checkDesignMode,
74298             scope: me,
74299             interval:100
74300         });
74301
74302         me.createToolbar(me);
74303         me.disableItems(true);
74304     },
74305
74306     initRenderTpl: function() {
74307         var me = this;
74308         if (!me.hasOwnProperty('renderTpl')) {
74309             me.renderTpl = me.getTpl('labelableRenderTpl');
74310         }
74311         return me.callParent();
74312     },
74313
74314     initRenderData: function() {
74315         return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
74316     },
74317
74318     getSubTplData: function() {
74319         var cssPrefix = Ext.baseCSSPrefix;
74320         return {
74321             cmpId: this.id,
74322             id: this.getInputId(),
74323             toolbarWrapCls: cssPrefix + 'html-editor-tb',
74324             textareaCls: cssPrefix + 'hidden',
74325             iframeName: Ext.id(),
74326             iframeSrc: Ext.SSL_SECURE_URL,
74327             size: 'height:100px;'
74328         };
74329     },
74330
74331     getSubTplMarkup: function() {
74332         var data = this.getSubTplData();
74333         return this.getTpl('fieldSubTpl').apply(data);
74334     },
74335
74336     getBodyNaturalWidth: function() {
74337         return 565;
74338     },
74339
74340     initFrameDoc: function() {
74341         var me = this,
74342             doc, task;
74343
74344         Ext.TaskManager.stop(me.monitorTask);
74345
74346         doc = me.getDoc();
74347         me.win = me.getWin();
74348
74349         doc.open();
74350         doc.write(me.getDocMarkup());
74351         doc.close();
74352
74353         task = { 
74354             run: function() {
74355                 var doc = me.getDoc();
74356                 if (doc.body || doc.readyState === 'complete') {
74357                     Ext.TaskManager.stop(task);
74358                     me.setDesignMode(true);
74359                     Ext.defer(me.initEditor, 10, me);
74360                 }
74361             },
74362             interval : 10,
74363             duration:10000,
74364             scope: me
74365         };
74366         Ext.TaskManager.start(task);
74367     },
74368
74369     checkDesignMode: function() {
74370         var me = this,
74371             doc = me.getDoc();
74372         if (doc && (!doc.editorInitialized || me.getDesignMode() !== 'on')) {
74373             me.initFrameDoc();
74374         }
74375     },
74376
74377     
74378     setDesignMode: function(mode) {
74379         var me = this,
74380             doc = me.getDoc();
74381         if (doc) {
74382             if (me.readOnly) {
74383                 mode = false;
74384             }
74385             doc.designMode = (/on|true/i).test(String(mode).toLowerCase()) ?'on':'off';
74386         }
74387     },
74388
74389     
74390     getDesignMode: function() {
74391         var doc = this.getDoc();
74392         return !doc ? '' : String(doc.designMode).toLowerCase();
74393     },
74394
74395     disableItems: function(disabled) {
74396         this.getToolbar().items.each(function(item){
74397             if(item.getItemId() !== 'sourceedit'){
74398                 item.setDisabled(disabled);
74399             }
74400         });
74401     },
74402
74403     
74404     toggleSourceEdit: function(sourceEditMode) {
74405         var me = this,
74406             iframe = me.iframeEl,
74407             textarea = me.textareaEl,
74408             hiddenCls = Ext.baseCSSPrefix + 'hidden',
74409             btn = me.getToolbar().getComponent('sourceedit');
74410
74411         if (!Ext.isBoolean(sourceEditMode)) {
74412             sourceEditMode = !me.sourceEditMode;
74413         }
74414         me.sourceEditMode = sourceEditMode;
74415
74416         if (btn.pressed !== sourceEditMode) {
74417             btn.toggle(sourceEditMode);
74418         }
74419         if (sourceEditMode) {
74420             me.disableItems(true);
74421             me.syncValue();
74422             iframe.addCls(hiddenCls);
74423             textarea.removeCls(hiddenCls);
74424             textarea.dom.removeAttribute('tabIndex');
74425             textarea.focus();
74426         }
74427         else {
74428             if (me.initialized) {
74429                 me.disableItems(me.readOnly);
74430             }
74431             me.pushValue();
74432             iframe.removeCls(hiddenCls);
74433             textarea.addCls(hiddenCls);
74434             textarea.dom.setAttribute('tabIndex', -1);
74435             me.deferFocus();
74436         }
74437         me.fireEvent('editmodechange', me, sourceEditMode);
74438         me.doComponentLayout();
74439     },
74440
74441     
74442     createLink : function() {
74443         var url = prompt(this.createLinkText, this.defaultLinkValue);
74444         if (url && url !== 'http:/'+'/') {
74445             this.relayCmd('createlink', url);
74446         }
74447     },
74448
74449     clearInvalid: Ext.emptyFn,
74450
74451     
74452     setValue: function(value) {
74453         var me = this,
74454             textarea = me.textareaEl;
74455         me.mixins.field.setValue.call(me, value);
74456         if (value === null || value === undefined) {
74457             value = '';
74458         }
74459         if (textarea) {
74460             textarea.dom.value = value;
74461         }
74462         me.pushValue();
74463         return this;
74464     },
74465
74466     
74467     cleanHtml: function(html) {
74468         html = String(html);
74469         if (Ext.isWebKit) { 
74470             html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
74471         }
74472
74473         
74474         if (html.charCodeAt(0) === this.defaultValue.replace(/\D/g, '')) {
74475             html = html.substring(1);
74476         }
74477         return html;
74478     },
74479
74480     
74481     syncValue : function(){
74482         var me = this,
74483             body, html, bodyStyle, match;
74484         if (me.initialized) {
74485             body = me.getEditorBody();
74486             html = body.innerHTML;
74487             if (Ext.isWebKit) {
74488                 bodyStyle = body.getAttribute('style'); 
74489                 match = bodyStyle.match(/text-align:(.*?);/i);
74490                 if (match && match[1]) {
74491                     html = '<div style="' + match[0] + '">' + html + '</div>';
74492                 }
74493             }
74494             html = me.cleanHtml(html);
74495             if (me.fireEvent('beforesync', me, html) !== false) {
74496                 me.textareaEl.dom.value = html;
74497                 me.fireEvent('sync', me, html);
74498             }
74499         }
74500     },
74501
74502     
74503     getValue : function() {
74504         var me = this,
74505             value;
74506         if (!me.sourceEditMode) {
74507             me.syncValue();
74508         }
74509         value = me.rendered ? me.textareaEl.dom.value : me.value;
74510         me.value = value;
74511         return value;
74512     },
74513
74514     
74515     pushValue: function() {
74516         var me = this,
74517             v;
74518         if(me.initialized){
74519             v = me.textareaEl.dom.value || '';
74520             if (!me.activated && v.length < 1) {
74521                 v = me.defaultValue;
74522             }
74523             if (me.fireEvent('beforepush', me, v) !== false) {
74524                 me.getEditorBody().innerHTML = v;
74525                 if (Ext.isGecko) {
74526                     
74527                     me.setDesignMode(false);  
74528                     me.setDesignMode(true);
74529                 }
74530                 me.fireEvent('push', me, v);
74531             }
74532         }
74533     },
74534
74535     
74536     deferFocus : function(){
74537          this.focus(false, true);
74538     },
74539
74540     getFocusEl: function() {
74541         var me = this,
74542             win = me.win;
74543         return win && !me.sourceEditMode ? win : me.textareaEl;
74544     },
74545
74546     
74547     initEditor : function(){
74548         
74549         try {
74550             var me = this,
74551                 dbody = me.getEditorBody(),
74552                 ss = me.textareaEl.getStyles('font-size', 'font-family', 'background-image', 'background-repeat', 'background-color', 'color'),
74553                 doc,
74554                 fn;
74555
74556             ss['background-attachment'] = 'fixed'; 
74557             dbody.bgProperties = 'fixed'; 
74558
74559             Ext.DomHelper.applyStyles(dbody, ss);
74560
74561             doc = me.getDoc();
74562
74563             if (doc) {
74564                 try {
74565                     Ext.EventManager.removeAll(doc);
74566                 } catch(e) {}
74567             }
74568
74569             
74570             fn = Ext.Function.bind(me.onEditorEvent, me);
74571             Ext.EventManager.on(doc, {
74572                 mousedown: fn,
74573                 dblclick: fn,
74574                 click: fn,
74575                 keyup: fn,
74576                 buffer:100
74577             });
74578
74579             
74580             
74581             
74582             
74583             
74584             fn = me.onRelayedEvent;
74585             Ext.EventManager.on(doc, {
74586                 mousedown: fn, 
74587                 mousemove: fn, 
74588                 mouseup: fn,   
74589                 click: fn,     
74590                 dblclick: fn,  
74591                 scope: me
74592             });
74593
74594             if (Ext.isGecko) {
74595                 Ext.EventManager.on(doc, 'keypress', me.applyCommand, me);
74596             }
74597             if (me.fixKeys) {
74598                 Ext.EventManager.on(doc, 'keydown', me.fixKeys, me);
74599             }
74600
74601             
74602             Ext.EventManager.on(window, 'unload', me.beforeDestroy, me);
74603             doc.editorInitialized = true;
74604
74605             me.initialized = true;
74606             me.pushValue();
74607             me.setReadOnly(me.readOnly);
74608             me.fireEvent('initialize', me);
74609         } catch(ex) {
74610             
74611         }
74612     },
74613
74614     
74615     beforeDestroy : function(){
74616         var me = this,
74617             monitorTask = me.monitorTask,
74618             doc, prop;
74619
74620         if (monitorTask) {
74621             Ext.TaskManager.stop(monitorTask);
74622         }
74623         if (me.rendered) {
74624             try {
74625                 doc = me.getDoc();
74626                 if (doc) {
74627                     Ext.EventManager.removeAll(doc);
74628                     for (prop in doc) {
74629                         if (doc.hasOwnProperty(prop)) {
74630                             delete doc[prop];
74631                         }
74632                     }
74633                 }
74634             } catch(e) {
74635                 
74636             }
74637             Ext.destroyMembers(me, 'tb', 'toolbarWrap', 'iframeEl', 'textareaEl');
74638         }
74639         me.callParent();
74640     },
74641
74642     
74643     onRelayedEvent: function (event) {
74644         
74645
74646         var iframeEl = this.iframeEl,
74647             iframeXY = iframeEl.getXY(),
74648             eventXY = event.getXY();
74649
74650         
74651         
74652         event.xy = [iframeXY[0] + eventXY[0], iframeXY[1] + eventXY[1]];
74653
74654         event.injectEvent(iframeEl); 
74655
74656         event.xy = eventXY; 
74657     },
74658
74659     
74660     onFirstFocus : function(){
74661         var me = this,
74662             selection, range;
74663         me.activated = true;
74664         me.disableItems(me.readOnly);
74665         if (Ext.isGecko) { 
74666             me.win.focus();
74667             selection = me.win.getSelection();
74668             if (!selection.focusNode || selection.focusNode.nodeType !== 3) {
74669                 range = selection.getRangeAt(0);
74670                 range.selectNodeContents(me.getEditorBody());
74671                 range.collapse(true);
74672                 me.deferFocus();
74673             }
74674             try {
74675                 me.execCmd('useCSS', true);
74676                 me.execCmd('styleWithCSS', false);
74677             } catch(e) {
74678                 
74679             }
74680         }
74681         me.fireEvent('activate', me);
74682     },
74683
74684     
74685     adjustFont: function(btn) {
74686         var adjust = btn.getItemId() === 'increasefontsize' ? 1 : -1,
74687             size = this.getDoc().queryCommandValue('FontSize') || '2',
74688             isPxSize = Ext.isString(size) && size.indexOf('px') !== -1,
74689             isSafari;
74690         size = parseInt(size, 10);
74691         if (isPxSize) {
74692             
74693             
74694             if (size <= 10) {
74695                 size = 1 + adjust;
74696             }
74697             else if (size <= 13) {
74698                 size = 2 + adjust;
74699             }
74700             else if (size <= 16) {
74701                 size = 3 + adjust;
74702             }
74703             else if (size <= 18) {
74704                 size = 4 + adjust;
74705             }
74706             else if (size <= 24) {
74707                 size = 5 + adjust;
74708             }
74709             else {
74710                 size = 6 + adjust;
74711             }
74712             size = Ext.Number.constrain(size, 1, 6);
74713         } else {
74714             isSafari = Ext.isSafari;
74715             if (isSafari) { 
74716                 adjust *= 2;
74717             }
74718             size = Math.max(1, size + adjust) + (isSafari ? 'px' : 0);
74719         }
74720         this.execCmd('FontSize', size);
74721     },
74722
74723     
74724     onEditorEvent: function(e) {
74725         this.updateToolbar();
74726     },
74727
74728     
74729     updateToolbar: function() {
74730         var me = this,
74731             btns, doc, name, fontSelect;
74732
74733         if (me.readOnly) {
74734             return;
74735         }
74736
74737         if (!me.activated) {
74738             me.onFirstFocus();
74739             return;
74740         }
74741
74742         btns = me.getToolbar().items.map;
74743         doc = me.getDoc();
74744
74745         if (me.enableFont && !Ext.isSafari2) {
74746             name = (doc.queryCommandValue('FontName') || me.defaultFont).toLowerCase();
74747             fontSelect = me.fontSelect.dom;
74748             if (name !== fontSelect.value) {
74749                 fontSelect.value = name;
74750             }
74751         }
74752
74753         function updateButtons() {
74754             Ext.Array.forEach(Ext.Array.toArray(arguments), function(name) {
74755                 btns[name].toggle(doc.queryCommandState(name));
74756             });
74757         }
74758         if(me.enableFormat){
74759             updateButtons('bold', 'italic', 'underline');
74760         }
74761         if(me.enableAlignments){
74762             updateButtons('justifyleft', 'justifycenter', 'justifyright');
74763         }
74764         if(!Ext.isSafari2 && me.enableLists){
74765             updateButtons('insertorderedlist', 'insertunorderedlist');
74766         }
74767
74768         Ext.menu.Manager.hideAll();
74769
74770         me.syncValue();
74771     },
74772
74773     
74774     relayBtnCmd: function(btn) {
74775         this.relayCmd(btn.getItemId());
74776     },
74777
74778     
74779     relayCmd: function(cmd, value) {
74780         Ext.defer(function() {
74781             var me = this;
74782             me.focus();
74783             me.execCmd(cmd, value);
74784             me.updateToolbar();
74785         }, 10, this);
74786     },
74787
74788     
74789     execCmd : function(cmd, value){
74790         var me = this,
74791             doc = me.getDoc(),
74792             undef;
74793         doc.execCommand(cmd, false, value === undef ? null : value);
74794         me.syncValue();
74795     },
74796
74797     
74798     applyCommand : function(e){
74799         if (e.ctrlKey) {
74800             var me = this,
74801                 c = e.getCharCode(), cmd;
74802             if (c > 0) {
74803                 c = String.fromCharCode(c);
74804                 switch (c) {
74805                     case 'b':
74806                         cmd = 'bold';
74807                     break;
74808                     case 'i':
74809                         cmd = 'italic';
74810                     break;
74811                     case 'u':
74812                         cmd = 'underline';
74813                     break;
74814                 }
74815                 if (cmd) {
74816                     me.win.focus();
74817                     me.execCmd(cmd);
74818                     me.deferFocus();
74819                     e.preventDefault();
74820                 }
74821             }
74822         }
74823     },
74824
74825     
74826     insertAtCursor : function(text){
74827         var me = this,
74828             range;
74829
74830         if (me.activated) {
74831             me.win.focus();
74832             if (Ext.isIE) {
74833                 range = me.getDoc().selection.createRange();
74834                 if (range) {
74835                     range.pasteHTML(text);
74836                     me.syncValue();
74837                     me.deferFocus();
74838                 }
74839             }else{
74840                 me.execCmd('InsertHTML', text);
74841                 me.deferFocus();
74842             }
74843         }
74844     },
74845
74846     
74847     fixKeys: function() { 
74848         if (Ext.isIE) {
74849             return function(e){
74850                 var me = this,
74851                     k = e.getKey(),
74852                     doc = me.getDoc(),
74853                     range, target;
74854                 if (k === e.TAB) {
74855                     e.stopEvent();
74856                     range = doc.selection.createRange();
74857                     if(range){
74858                         range.collapse(true);
74859                         range.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');
74860                         me.deferFocus();
74861                     }
74862                 }
74863                 else if (k === e.ENTER) {
74864                     range = doc.selection.createRange();
74865                     if (range) {
74866                         target = range.parentElement();
74867                         if(!target || target.tagName.toLowerCase() !== 'li'){
74868                             e.stopEvent();
74869                             range.pasteHTML('<br />');
74870                             range.collapse(false);
74871                             range.select();
74872                         }
74873                     }
74874                 }
74875             };
74876         }
74877
74878         if (Ext.isOpera) {
74879             return function(e){
74880                 var me = this;
74881                 if (e.getKey() === e.TAB) {
74882                     e.stopEvent();
74883                     me.win.focus();
74884                     me.execCmd('InsertHTML','&nbsp;&nbsp;&nbsp;&nbsp;');
74885                     me.deferFocus();
74886                 }
74887             };
74888         }
74889
74890         if (Ext.isWebKit) {
74891             return function(e){
74892                 var me = this,
74893                     k = e.getKey();
74894                 if (k === e.TAB) {
74895                     e.stopEvent();
74896                     me.execCmd('InsertText','\t');
74897                     me.deferFocus();
74898                 }
74899                 else if (k === e.ENTER) {
74900                     e.stopEvent();
74901                     me.execCmd('InsertHtml','<br /><br />');
74902                     me.deferFocus();
74903                 }
74904             };
74905         }
74906
74907         return null; 
74908     }(),
74909
74910     
74911     getToolbar : function(){
74912         return this.toolbar;
74913     },
74914
74915     
74916     buttonTips : {
74917         bold : {
74918             title: 'Bold (Ctrl+B)',
74919             text: 'Make the selected text bold.',
74920             cls: Ext.baseCSSPrefix + 'html-editor-tip'
74921         },
74922         italic : {
74923             title: 'Italic (Ctrl+I)',
74924             text: 'Make the selected text italic.',
74925             cls: Ext.baseCSSPrefix + 'html-editor-tip'
74926         },
74927         underline : {
74928             title: 'Underline (Ctrl+U)',
74929             text: 'Underline the selected text.',
74930             cls: Ext.baseCSSPrefix + 'html-editor-tip'
74931         },
74932         increasefontsize : {
74933             title: 'Grow Text',
74934             text: 'Increase the font size.',
74935             cls: Ext.baseCSSPrefix + 'html-editor-tip'
74936         },
74937         decreasefontsize : {
74938             title: 'Shrink Text',
74939             text: 'Decrease the font size.',
74940             cls: Ext.baseCSSPrefix + 'html-editor-tip'
74941         },
74942         backcolor : {
74943             title: 'Text Highlight Color',
74944             text: 'Change the background color of the selected text.',
74945             cls: Ext.baseCSSPrefix + 'html-editor-tip'
74946         },
74947         forecolor : {
74948             title: 'Font Color',
74949             text: 'Change the color of the selected text.',
74950             cls: Ext.baseCSSPrefix + 'html-editor-tip'
74951         },
74952         justifyleft : {
74953             title: 'Align Text Left',
74954             text: 'Align text to the left.',
74955             cls: Ext.baseCSSPrefix + 'html-editor-tip'
74956         },
74957         justifycenter : {
74958             title: 'Center Text',
74959             text: 'Center text in the editor.',
74960             cls: Ext.baseCSSPrefix + 'html-editor-tip'
74961         },
74962         justifyright : {
74963             title: 'Align Text Right',
74964             text: 'Align text to the right.',
74965             cls: Ext.baseCSSPrefix + 'html-editor-tip'
74966         },
74967         insertunorderedlist : {
74968             title: 'Bullet List',
74969             text: 'Start a bulleted list.',
74970             cls: Ext.baseCSSPrefix + 'html-editor-tip'
74971         },
74972         insertorderedlist : {
74973             title: 'Numbered List',
74974             text: 'Start a numbered list.',
74975             cls: Ext.baseCSSPrefix + 'html-editor-tip'
74976         },
74977         createlink : {
74978             title: 'Hyperlink',
74979             text: 'Make the selected text a hyperlink.',
74980             cls: Ext.baseCSSPrefix + 'html-editor-tip'
74981         },
74982         sourceedit : {
74983             title: 'Source Edit',
74984             text: 'Switch to source editing mode.',
74985             cls: Ext.baseCSSPrefix + 'html-editor-tip'
74986         }
74987     }
74988
74989     
74990     
74991     
74992     
74993     
74994     
74995     
74996     
74997     
74998     
74999     
75000     
75001     
75002     
75003     
75004     
75005     
75006 });
75007
75008
75009 Ext.define('Ext.form.field.Radio', {
75010     extend:'Ext.form.field.Checkbox',
75011     alias: ['widget.radiofield', 'widget.radio'],
75012     alternateClassName: 'Ext.form.Radio',
75013     requires: ['Ext.form.RadioManager'],
75014
75015     isRadio: true,
75016
75017     
75018
75019     
75020     inputType: 'radio',
75021     ariaRole: 'radio',
75022
75023     
75024     getGroupValue: function() {
75025         var selected = this.getManager().getChecked(this.name);
75026         return selected ? selected.inputValue : null;
75027     },
75028
75029     
75030     onBoxClick: function(e) {
75031         var me = this;
75032         if (!me.disabled && !me.readOnly) {
75033             this.setValue(true);
75034         }
75035     },
75036
75037     
75038     setValue: function(v) {
75039         var me = this,
75040             active;
75041
75042         if (Ext.isBoolean(v)) {
75043             me.callParent(arguments);
75044         } else {
75045             active = me.getManager().getWithValue(me.name, v).getAt(0);
75046             if (active) {
75047                 active.setValue(true);
75048             }
75049         }
75050         return me;
75051     },
75052
75053     
75054     getSubmitValue: function() {
75055         return this.checked ? this.inputValue : null;
75056     },
75057
75058     getModelData: function() {
75059         return this.getSubmitData();
75060     },
75061
75062     
75063     onChange: function(newVal, oldVal) {
75064         var me = this;
75065         me.callParent(arguments);
75066
75067         if (newVal) {
75068             this.getManager().getByName(me.name).each(function(item){
75069                 if (item !== me) {
75070                     item.setValue(false);
75071                 }
75072             }, me);
75073         }
75074     },
75075
75076     
75077     getManager: function() {
75078         return Ext.form.RadioManager;
75079     }
75080 });
75081
75082
75083 Ext.define('Ext.picker.Time', {
75084     extend: 'Ext.view.BoundList',
75085     alias: 'widget.timepicker',
75086     requires: ['Ext.data.Store', 'Ext.Date'],
75087
75088     
75089
75090     
75091
75092     
75093     increment: 15,
75094
75095     
75096     format : "g:i A",
75097
75098     
75099     displayField: 'disp',
75100
75101     
75102     initDate: [2008,0,1],
75103
75104     componentCls: Ext.baseCSSPrefix + 'timepicker',
75105
75106     
75107     loadMask: false,
75108
75109     initComponent: function() {
75110         var me = this,
75111             dateUtil = Ext.Date,
75112             clearTime = dateUtil.clearTime,
75113             initDate = me.initDate;
75114
75115         
75116         me.absMin = clearTime(new Date(initDate[0], initDate[1], initDate[2]));
75117         me.absMax = dateUtil.add(clearTime(new Date(initDate[0], initDate[1], initDate[2])), 'mi', (24 * 60) - 1);
75118
75119         me.store = me.createStore();
75120         me.updateList();
75121
75122         me.callParent();
75123     },
75124
75125     
75126     setMinValue: function(value) {
75127         this.minValue = value;
75128         this.updateList();
75129     },
75130
75131     
75132     setMaxValue: function(value) {
75133         this.maxValue = value;
75134         this.updateList();
75135     },
75136
75137     
75138     normalizeDate: function(date) {
75139         var initDate = this.initDate;
75140         date.setFullYear(initDate[0], initDate[1], initDate[2]);
75141         return date;
75142     },
75143
75144     
75145     updateList: function() {
75146         var me = this,
75147             min = me.normalizeDate(me.minValue || me.absMin),
75148             max = me.normalizeDate(me.maxValue || me.absMax);
75149
75150         me.store.filterBy(function(record) {
75151             var date = record.get('date');
75152             return date >= min && date <= max;
75153         });
75154     },
75155
75156     
75157     createStore: function() {
75158         var me = this,
75159             utilDate = Ext.Date,
75160             times = [],
75161             min = me.absMin,
75162             max = me.absMax;
75163
75164         while(min <= max){
75165             times.push({
75166                 disp: utilDate.dateFormat(min, me.format),
75167                 date: min
75168             });
75169             min = utilDate.add(min, 'mi', me.increment);
75170         }
75171
75172         return Ext.create('Ext.data.Store', {
75173             fields: ['disp', 'date'],
75174             data: times
75175         });
75176     }
75177
75178 });
75179
75180
75181 Ext.define('Ext.form.field.Time', {
75182     extend:'Ext.form.field.Picker',
75183     alias: 'widget.timefield',
75184     requires: ['Ext.form.field.Date', 'Ext.picker.Time', 'Ext.view.BoundListKeyNav', 'Ext.Date'],
75185     alternateClassName: ['Ext.form.TimeField', 'Ext.form.Time'],
75186
75187     
75188     triggerCls: Ext.baseCSSPrefix + 'form-time-trigger',
75189
75190     
75191
75192     
75193
75194     
75195     minText : "The time in this field must be equal to or after {0}",
75196
75197     
75198     maxText : "The time in this field must be equal to or before {0}",
75199
75200     
75201     invalidText : "{0} is not a valid time",
75202
75203     
75204     format : "g:i A",
75205
75206     
75207
75208     
75209     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",
75210
75211     
75212     increment: 15,
75213
75214     
75215     pickerMaxHeight: 300,
75216
75217     
75218     selectOnTab: true,
75219
75220     
75221     initDate: '1/1/2008',
75222     initDateFormat: 'j/n/Y',
75223
75224
75225     initComponent: function() {
75226         var me = this,
75227             min = me.minValue,
75228             max = me.maxValue;
75229         if (min) {
75230             me.setMinValue(min);
75231         }
75232         if (max) {
75233             me.setMaxValue(max);
75234         }
75235         this.callParent();
75236     },
75237
75238     initValue: function() {
75239         var me = this,
75240             value = me.value;
75241
75242         
75243         if (Ext.isString(value)) {
75244             me.value = me.rawToValue(value);
75245         }
75246
75247         me.callParent();
75248     },
75249
75250     
75251     setMinValue: function(value) {
75252         var me = this,
75253             picker = me.picker;
75254         me.setLimit(value, true);
75255         if (picker) {
75256             picker.setMinValue(me.minValue);
75257         }
75258     },
75259
75260     
75261     setMaxValue: function(value) {
75262         var me = this,
75263             picker = me.picker;
75264         me.setLimit(value, false);
75265         if (picker) {
75266             picker.setMaxValue(me.maxValue);
75267         }
75268     },
75269
75270     
75271     setLimit: function(value, isMin) {
75272         var me = this,
75273             d, val;
75274         if (Ext.isString(value)) {
75275             d = me.parseDate(value);
75276         }
75277         else if (Ext.isDate(value)) {
75278             d = value;
75279         }
75280         if (d) {
75281             val = Ext.Date.clearTime(new Date(me.initDate));
75282             val.setHours(d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
75283             me[isMin ? 'minValue' : 'maxValue'] = val;
75284         }
75285     },
75286
75287     rawToValue: function(rawValue) {
75288         return this.parseDate(rawValue) || rawValue || null;
75289     },
75290
75291     valueToRaw: function(value) {
75292         return this.formatDate(this.parseDate(value));
75293     },
75294
75295     
75296     getErrors: function(value) {
75297         var me = this,
75298             format = Ext.String.format,
75299             errors = me.callParent(arguments),
75300             minValue = me.minValue,
75301             maxValue = me.maxValue,
75302             date;
75303
75304         value = me.formatDate(value || me.processRawValue(me.getRawValue()));
75305
75306         if (value === null || value.length < 1) { 
75307              return errors;
75308         }
75309
75310         date = me.parseDate(value);
75311         if (!date) {
75312             errors.push(format(me.invalidText, value, me.format));
75313             return errors;
75314         }
75315
75316         if (minValue && date < minValue) {
75317             errors.push(format(me.minText, me.formatDate(minValue)));
75318         }
75319
75320         if (maxValue && date > maxValue) {
75321             errors.push(format(me.maxText, me.formatDate(maxValue)));
75322         }
75323
75324         return errors;
75325     },
75326
75327     formatDate: function() {
75328         return Ext.form.field.Date.prototype.formatDate.apply(this, arguments);
75329     },
75330
75331     
75332     parseDate: function(value) {
75333         if (!value || Ext.isDate(value)) {
75334             return value;
75335         }
75336
75337         var me = this,
75338             val = me.safeParse(value, me.format),
75339             altFormats = me.altFormats,
75340             altFormatsArray = me.altFormatsArray,
75341             i = 0,
75342             len;
75343
75344         if (!val && altFormats) {
75345             altFormatsArray = altFormatsArray || altFormats.split('|');
75346             len = altFormatsArray.length;
75347             for (; i < len && !val; ++i) {
75348                 val = me.safeParse(value, altFormatsArray[i]);
75349             }
75350         }
75351         return val;
75352     },
75353
75354     safeParse: function(value, format){
75355         var me = this,
75356             utilDate = Ext.Date,
75357             parsedDate,
75358             result = null;
75359
75360         if (utilDate.formatContainsDateInfo(format)) {
75361             
75362             result = utilDate.parse(value, format);
75363         } else {
75364             
75365             parsedDate = utilDate.parse(me.initDate + ' ' + value, me.initDateFormat + ' ' + format);
75366             if (parsedDate) {
75367                 result = parsedDate;
75368             }
75369         }
75370         return result;
75371     },
75372
75373     
75374     getSubmitValue: function() {
75375         var me = this,
75376             format = me.submitFormat || me.format,
75377             value = me.getValue();
75378
75379         return value ? Ext.Date.format(value, format) : null;
75380     },
75381
75382     
75383     createPicker: function() {
75384         var me = this,
75385             picker = Ext.create('Ext.picker.Time', {
75386                 pickerField: me,
75387                 selModel: {
75388                     mode: 'SINGLE'
75389                 },
75390                 floating: true,
75391                 hidden: true,
75392                 minValue: me.minValue,
75393                 maxValue: me.maxValue,
75394                 increment: me.increment,
75395                 format: me.format,
75396                 ownerCt: this.ownerCt,
75397                 renderTo: document.body,
75398                 maxHeight: me.pickerMaxHeight,
75399                 focusOnToFront: false
75400             });
75401
75402         me.mon(picker.getSelectionModel(), {
75403             selectionchange: me.onListSelect,
75404             scope: me
75405         });
75406
75407         return picker;
75408     },
75409
75410     
75411     onExpand: function() {
75412         var me = this,
75413             keyNav = me.pickerKeyNav,
75414             selectOnTab = me.selectOnTab,
75415             picker = me.getPicker(),
75416             lastSelected = picker.getSelectionModel().lastSelected,
75417             itemNode;
75418
75419         if (!keyNav) {
75420             keyNav = me.pickerKeyNav = Ext.create('Ext.view.BoundListKeyNav', this.inputEl, {
75421                 boundList: picker,
75422                 forceKeyDown: true,
75423                 tab: function(e) {
75424                     if (selectOnTab) {
75425                         if(me.picker.highlightedItem) {
75426                             this.selectHighlighted(e);
75427                         } else {
75428                             me.collapse();
75429                         }
75430                         me.triggerBlur();
75431                     }
75432                     
75433                     return true;
75434                 }
75435             });
75436             
75437             if (selectOnTab) {
75438                 me.ignoreMonitorTab = true;
75439             }
75440         }
75441         Ext.defer(keyNav.enable, 1, keyNav); 
75442
75443         
75444         if (lastSelected) {
75445             itemNode = picker.getNode(lastSelected);
75446             if (itemNode) {
75447                 picker.highlightItem(itemNode);
75448                 picker.el.scrollChildIntoView(itemNode, false);
75449             }
75450         }
75451     },
75452
75453     
75454     onCollapse: function() {
75455         var me = this,
75456             keyNav = me.pickerKeyNav;
75457         if (keyNav) {
75458             keyNav.disable();
75459             me.ignoreMonitorTab = false;
75460         }
75461     },
75462
75463     
75464     onChange: function() {
75465         var me = this,
75466             picker = me.picker;
75467
75468         me.callParent(arguments);
75469         if(picker) {
75470             picker.clearHighlight();
75471         }
75472     },
75473
75474     
75475     onListSelect: function(list, recordArray) {
75476         var me = this,
75477             record = recordArray[0],
75478             val = record ? record.get('date') : null;
75479         me.setValue(val);
75480         me.fireEvent('select', me, val);
75481         me.picker.clearHighlight();
75482         me.collapse();
75483         me.inputEl.focus();
75484     }
75485 });
75486
75487
75488
75489 Ext.define('Ext.grid.CellEditor', {
75490     extend: 'Ext.Editor',
75491     constructor: function(config) {
75492         config = Ext.apply({}, config);
75493         
75494         if (config.field) {
75495             config.field.monitorTab = false;
75496         }
75497         if (!Ext.isDefined(config.autoSize)) {
75498             config.autoSize = {
75499                 width: 'boundEl'
75500             };
75501         }
75502         this.callParent([config]);
75503     },
75504     
75505     
75506     onShow: function() {
75507         var first = this.boundEl.first();
75508         if (first) {
75509             first.hide();
75510         }
75511         this.callParent(arguments);
75512     },
75513     
75514     
75515     onHide: function() {
75516         var first = this.boundEl.first();
75517         if (first) {
75518             first.show();
75519         }
75520         this.callParent(arguments);
75521     },
75522     
75523     
75524     afterRender: function() {
75525         this.callParent(arguments);
75526         var field = this.field;
75527         if (field.isXType('checkboxfield')) {
75528             field.mon(field.inputEl, 'mousedown', this.onCheckBoxMouseDown, this);
75529             field.mon(field.inputEl, 'click', this.onCheckBoxClick, this);
75530         }
75531     },
75532     
75533     
75534     onCheckBoxMouseDown: function() {
75535         this.completeEdit = Ext.emptyFn;
75536     },
75537     
75538     
75539     onCheckBoxClick: function() {
75540         delete this.completeEdit;
75541         this.field.focus(false, 10);
75542     },
75543     
75544     alignment: "tl-tl",
75545     hideEl : false,
75546     cls: Ext.baseCSSPrefix + "small-editor " + Ext.baseCSSPrefix + "grid-editor",
75547     shim: false,
75548     shadow: false
75549 });
75550
75551 Ext.define('Ext.grid.ColumnLayout', {
75552     extend: 'Ext.layout.container.HBox',
75553     alias: 'layout.gridcolumn',
75554     type : 'column',
75555
75556     reserveOffset: false,
75557
75558     shrinkToFit: false,
75559
75560     
75561     clearInnerCtOnLayout: true,
75562
75563     beforeLayout: function() {
75564         var me = this,
75565             i = 0,
75566             items = me.getLayoutItems(),
75567             len = items.length,
75568             item, returnValue,
75569             s;
75570
75571         
75572         if (!Ext.isDefined(me.availableSpaceOffset)) {
75573             s = me.owner.up('tablepanel').verticalScroller;
75574             me.availableSpaceOffset = s ? s.width-1 : 0;
75575         }
75576
75577         returnValue = me.callParent(arguments);
75578
75579         
75580         me.innerCt.setHeight(23);
75581
75582         
75583         for (; i < len; i++) {
75584             item = items[i];
75585             item.el.setStyle({
75586                 height: 'auto'
75587             });
75588             item.titleContainer.setStyle({
75589                 height: 'auto',
75590                 paddingTop: '0'
75591             });
75592             if (item.componentLayout && item.componentLayout.lastComponentSize) {
75593                 item.componentLayout.lastComponentSize.height = item.el.dom.offsetHeight;
75594             }
75595         }
75596         return returnValue;
75597     },
75598
75599     
75600     calculateChildBoxes: function(visibleItems, targetSize) {
75601         var me = this,
75602             calculations = me.callParent(arguments),
75603             boxes = calculations.boxes,
75604             metaData = calculations.meta,
75605             len = boxes.length, i = 0, box, item;
75606
75607         if (targetSize.width && !me.isHeader) {
75608             
75609             if (me.owner.forceFit) {
75610
75611                 for (; i < len; i++) {
75612                     box = boxes[i];
75613                     item = box.component;
75614
75615                     
75616                     item.minWidth = Ext.grid.plugin.HeaderResizer.prototype.minColWidth;
75617
75618                     
75619                     
75620                     item.flex = box.width;
75621                 }
75622
75623                 
75624                 calculations = me.callParent(arguments);
75625             }
75626             else if (metaData.tooNarrow) {
75627                 targetSize.width = metaData.desiredSize;
75628             }
75629         }
75630
75631         return calculations;
75632     },
75633
75634     afterLayout: function() {
75635         var me = this,
75636             owner = me.owner,
75637             topGrid,
75638             bothHeaderCts,
75639             otherHeaderCt,
75640             thisHeight,
75641             otherHeight,
75642             modifiedGrid,
75643             i = 0,
75644             items,
75645             len,
75646             headerHeight;
75647
75648         me.callParent(arguments);
75649
75650         
75651         if (!me.owner.hideHeaders) {
75652
75653             
75654             
75655             if (owner.lockableInjected) {
75656                 topGrid = owner.up('tablepanel').up('tablepanel');
75657                 bothHeaderCts = topGrid.query('headercontainer:not([isHeader])');
75658                 otherHeaderCt = (bothHeaderCts[0] === owner) ? bothHeaderCts[1] : bothHeaderCts[0];
75659
75660                 
75661                 if (!otherHeaderCt.rendered) {
75662                     return;
75663                 }
75664
75665                 
75666                 otherHeight = otherHeaderCt.layout.getRenderTarget().getViewSize().height;
75667                 if (!otherHeight) {
75668                     return;
75669                 }
75670                 thisHeight = this.getRenderTarget().getViewSize().height;
75671                 if (!thisHeight) {
75672                     return;
75673                 }
75674
75675                 
75676                 
75677                 topGrid.componentLayout.layoutBusy = true;
75678
75679                 
75680                 headerHeight = thisHeight;
75681
75682                 
75683                 if (thisHeight > otherHeight) {
75684                     otherHeaderCt.layout.align = 'stretch';
75685                     otherHeaderCt.setCalculatedSize(otherHeaderCt.getWidth(), owner.getHeight(), otherHeaderCt.ownerCt);
75686                     delete otherHeaderCt.layout.align;
75687                     modifiedGrid = otherHeaderCt.up('tablepanel');
75688                 } else if (otherHeight > thisHeight) {
75689                     headerHeight = otherHeight;
75690                     this.align = 'stretch';
75691                     owner.setCalculatedSize(owner.getWidth(), otherHeaderCt.getHeight(), owner.ownerCt);
75692                     delete this.align;
75693                     modifiedGrid = owner.up('tablepanel');
75694                 }
75695                 topGrid.componentLayout.layoutBusy = false;
75696
75697                 
75698                 items = bothHeaderCts[0].layout.getLayoutItems().concat(bothHeaderCts[1].layout.getLayoutItems());
75699             } else {
75700                 headerHeight = this.getRenderTarget().getViewSize().height;
75701                 items = me.getLayoutItems();
75702             }
75703
75704             len = items.length;
75705             for (; i < len; i++) {
75706                 items[i].setPadding(headerHeight);
75707             }
75708
75709             
75710             if (modifiedGrid) {
75711                 setTimeout(function() {
75712                     modifiedGrid.doLayout();
75713                 }, 1);
75714             }
75715         }
75716     },
75717
75718     
75719     
75720     updateInnerCtSize: function(tSize, calcs) {
75721         var me = this,
75722             extra;
75723
75724         
75725         if (!me.isHeader) {
75726             me.tooNarrow = calcs.meta.tooNarrow;
75727             extra = (me.reserveOffset ? me.availableSpaceOffset : 0);
75728
75729             if (calcs.meta.tooNarrow) {
75730                 tSize.width = calcs.meta.desiredSize + extra;
75731             } else {
75732                 tSize.width += extra;
75733             }
75734         }
75735
75736         return me.callParent(arguments);
75737     },
75738
75739     doOwnerCtLayouts: function() {
75740         var ownerCt = this.owner.ownerCt;
75741         if (!ownerCt.componentLayout.layoutBusy) {
75742             ownerCt.doComponentLayout();
75743         }
75744     }
75745 });
75746
75747 Ext.define('Ext.grid.LockingView', {
75748
75749     mixins: {
75750         observable: 'Ext.util.Observable'
75751     },
75752
75753     eventRelayRe: /^(beforeitem|beforecontainer|item|container|cell)/,
75754
75755     constructor: function(config){
75756         var me = this,
75757             eventNames = [],
75758             eventRe = me.eventRelayRe,
75759             locked = config.locked.getView(),
75760             normal = config.normal.getView(),
75761             events,
75762             event;
75763
75764         Ext.apply(me, {
75765             lockedView: locked,
75766             normalView: normal,
75767             lockedGrid: config.locked,
75768             normalGrid: config.normal,
75769             panel: config.panel
75770         });
75771         me.mixins.observable.constructor.call(me, config);
75772
75773         
75774         events = locked.events;
75775         for (event in events) {
75776             if (events.hasOwnProperty(event) && eventRe.test(event)) {
75777                 eventNames.push(event);
75778             }
75779         }
75780         me.relayEvents(locked, eventNames);
75781         me.relayEvents(normal, eventNames);
75782
75783         normal.on({
75784             scope: me,
75785             itemmouseleave: me.onItemMouseLeave,
75786             itemmouseenter: me.onItemMouseEnter
75787         });
75788
75789         locked.on({
75790             scope: me,
75791             itemmouseleave: me.onItemMouseLeave,
75792             itemmouseenter: me.onItemMouseEnter
75793         });
75794     },
75795
75796     getGridColumns: function() {
75797         var cols = this.lockedGrid.headerCt.getGridColumns();
75798         return cols.concat(this.normalGrid.headerCt.getGridColumns());
75799     },
75800
75801     getEl: function(column){
75802         return this.getViewForColumn(column).getEl();
75803     },
75804
75805     getViewForColumn: function(column) {
75806         var view = this.lockedView,
75807             inLocked;
75808
75809         view.headerCt.cascade(function(col){
75810             if (col === column) {
75811                 inLocked = true;
75812                 return false;
75813             }
75814         });
75815
75816         return inLocked ? view : this.normalView;
75817     },
75818
75819     onItemMouseEnter: function(view, record){
75820         var me = this,
75821             locked = me.lockedView,
75822             other = me.normalView,
75823             item;
75824
75825         if (view.trackOver) {
75826             if (view !== locked) {
75827                 other = locked;
75828             }
75829             item = other.getNode(record);
75830             other.highlightItem(item);
75831         }
75832     },
75833
75834     onItemMouseLeave: function(view, record){
75835         var me = this,
75836             locked = me.lockedView,
75837             other = me.normalView;
75838
75839         if (view.trackOver) {
75840             if (view !== locked) {
75841                 other = locked;
75842             }
75843             other.clearHighlight();
75844         }
75845     },
75846
75847     relayFn: function(name, args){
75848         args = args || [];
75849
75850         var view = this.lockedView;
75851         view[name].apply(view, args || []);
75852         view = this.normalView;
75853         view[name].apply(view, args || []);
75854     },
75855
75856     getSelectionModel: function(){
75857         return this.panel.getSelectionModel();
75858     },
75859
75860     getStore: function(){
75861         return this.panel.store;
75862     },
75863
75864     getNode: function(nodeInfo){
75865         
75866         return this.normalView.getNode(nodeInfo);
75867     },
75868
75869     getCell: function(record, column){
75870         var view = this.getViewForColumn(column),
75871             row;
75872
75873         row = view.getNode(record);
75874         return Ext.fly(row).down(column.getCellSelector());
75875     },
75876
75877     getRecord: function(node){
75878         var result = this.lockedView.getRecord(node);
75879         if (!node) {
75880             result = this.normalView.getRecord(node);
75881         }
75882         return result;
75883     },
75884
75885     addElListener: function(eventName, fn, scope){
75886         this.relayFn('addElListener', arguments);
75887     },
75888
75889     refreshNode: function(){
75890         this.relayFn('refreshNode', arguments);
75891     },
75892
75893     refresh: function(){
75894         this.relayFn('refresh', arguments);
75895     },
75896
75897     bindStore: function(){
75898         this.relayFn('bindStore', arguments);
75899     },
75900
75901     addRowCls: function(){
75902         this.relayFn('addRowCls', arguments);
75903     },
75904
75905     removeRowCls: function(){
75906         this.relayFn('removeRowCls', arguments);
75907     }
75908
75909 });
75910
75911 Ext.define('Ext.grid.Lockable', {
75912
75913     requires: ['Ext.grid.LockingView'],
75914
75915     
75916     syncRowHeight: true,
75917
75918     
75919
75920     
75921
75922     
75923
75924     
75925     spacerHidden: true,
75926
75927     headerCounter: 0,
75928
75929     
75930     unlockText: 'Unlock',
75931     lockText: 'Lock',
75932
75933     determineXTypeToCreate: function() {
75934         var me = this,
75935             typeToCreate;
75936
75937         if (me.subGridXType) {
75938             typeToCreate = me.subGridXType;
75939         } else {
75940             var xtypes     = this.getXTypes().split('/'),
75941                 xtypesLn   = xtypes.length,
75942                 xtype      = xtypes[xtypesLn - 1],
75943                 superxtype = xtypes[xtypesLn - 2];
75944
75945             if (superxtype !== 'tablepanel') {
75946                 typeToCreate = superxtype;
75947             } else {
75948                 typeToCreate = xtype;
75949             }
75950         }
75951
75952         return typeToCreate;
75953     },
75954
75955     
75956     
75957     injectLockable: function() {
75958         
75959         this.lockable = true;
75960         
75961         
75962         this.hasView = true;
75963
75964         var me = this,
75965             
75966             
75967             
75968             xtype = me.determineXTypeToCreate(),
75969             
75970             selModel = me.getSelectionModel(),
75971             lockedGrid = {
75972                 xtype: xtype,
75973                 
75974                 enableAnimations: false,
75975                 scroll: false,
75976                 scrollerOwner: false,
75977                 selModel: selModel,
75978                 border: false,
75979                 cls: Ext.baseCSSPrefix + 'grid-inner-locked'
75980             },
75981             normalGrid = {
75982                 xtype: xtype,
75983                 enableAnimations: false,
75984                 scrollerOwner: false,
75985                 selModel: selModel,
75986                 border: false
75987             },
75988             i = 0,
75989             columns,
75990             lockedHeaderCt,
75991             normalHeaderCt;
75992
75993         me.addCls(Ext.baseCSSPrefix + 'grid-locked');
75994
75995         
75996         
75997         
75998         Ext.copyTo(normalGrid, me, me.normalCfgCopy);
75999         Ext.copyTo(lockedGrid, me, me.lockedCfgCopy);
76000         for (; i < me.normalCfgCopy.length; i++) {
76001             delete me[me.normalCfgCopy[i]];
76002         }
76003         for (i = 0; i < me.lockedCfgCopy.length; i++) {
76004             delete me[me.lockedCfgCopy[i]];
76005         }
76006
76007         me.addEvents(
76008             
76009             'lockcolumn',
76010
76011             
76012             'unlockcolumn'
76013         );
76014
76015         me.addStateEvents(['lockcolumn', 'unlockcolumn']);
76016
76017         me.lockedHeights = [];
76018         me.normalHeights = [];
76019
76020         columns = me.processColumns(me.columns);
76021
76022         lockedGrid.width = columns.lockedWidth + Ext.num(selModel.headerWidth, 0);
76023         lockedGrid.columns = columns.locked;
76024         normalGrid.columns = columns.normal;
76025
76026         me.store = Ext.StoreManager.lookup(me.store);
76027         lockedGrid.store = me.store;
76028         normalGrid.store = me.store;
76029
76030         
76031         normalGrid.flex = 1;
76032         lockedGrid.viewConfig = me.lockedViewConfig || {};
76033         lockedGrid.viewConfig.loadingUseMsg = false;
76034         normalGrid.viewConfig = me.normalViewConfig || {};
76035
76036         Ext.applyIf(lockedGrid.viewConfig, me.viewConfig);
76037         Ext.applyIf(normalGrid.viewConfig, me.viewConfig);
76038
76039         me.normalGrid = Ext.ComponentManager.create(normalGrid);
76040         me.lockedGrid = Ext.ComponentManager.create(lockedGrid);
76041
76042         me.view = Ext.create('Ext.grid.LockingView', {
76043             locked: me.lockedGrid,
76044             normal: me.normalGrid,
76045             panel: me
76046         });
76047
76048         if (me.syncRowHeight) {
76049             me.lockedGrid.getView().on({
76050                 refresh: me.onLockedGridAfterRefresh,
76051                 itemupdate: me.onLockedGridAfterUpdate,
76052                 scope: me
76053             });
76054
76055             me.normalGrid.getView().on({
76056                 refresh: me.onNormalGridAfterRefresh,
76057                 itemupdate: me.onNormalGridAfterUpdate,
76058                 scope: me
76059             });
76060         }
76061
76062         lockedHeaderCt = me.lockedGrid.headerCt;
76063         normalHeaderCt = me.normalGrid.headerCt;
76064
76065         lockedHeaderCt.lockedCt = true;
76066         lockedHeaderCt.lockableInjected = true;
76067         normalHeaderCt.lockableInjected = true;
76068
76069         lockedHeaderCt.on({
76070             columnshow: me.onLockedHeaderShow,
76071             columnhide: me.onLockedHeaderHide,
76072             columnmove: me.onLockedHeaderMove,
76073             sortchange: me.onLockedHeaderSortChange,
76074             columnresize: me.onLockedHeaderResize,
76075             scope: me
76076         });
76077
76078         normalHeaderCt.on({
76079             columnmove: me.onNormalHeaderMove,
76080             sortchange: me.onNormalHeaderSortChange,
76081             scope: me
76082         });
76083
76084         me.normalGrid.on({
76085             scrollershow: me.onScrollerShow,
76086             scrollerhide: me.onScrollerHide,
76087             scope: me
76088         });
76089
76090         me.lockedGrid.on('afterlayout', me.onLockedGridAfterLayout, me, {single: true});
76091
76092         me.modifyHeaderCt();
76093         me.items = [me.lockedGrid, me.normalGrid];
76094
76095         me.relayHeaderCtEvents(lockedHeaderCt);
76096         me.relayHeaderCtEvents(normalHeaderCt);
76097
76098         me.layout = {
76099             type: 'hbox',
76100             align: 'stretch'
76101         };
76102     },
76103
76104     processColumns: function(columns){
76105         
76106         var i = 0,
76107             len = columns.length,
76108             lockedWidth = 1,
76109             lockedHeaders = [],
76110             normalHeaders = [],
76111             column;
76112
76113         for (; i < len; ++i) {
76114             column = columns[i];
76115             
76116             
76117             column.processed = true;
76118             if (column.locked) {
76119                 if (!column.hidden) {
76120                     lockedWidth += column.width || Ext.grid.header.Container.prototype.defaultWidth;
76121                 }
76122                 lockedHeaders.push(column);
76123             } else {
76124                 normalHeaders.push(column);
76125             }
76126             if (!column.headerId) {
76127                 column.headerId = (column.initialConfig || column).id || ('L' + (++this.headerCounter));
76128             }
76129         }
76130         return {
76131             lockedWidth: lockedWidth,
76132             locked: lockedHeaders,
76133             normal: normalHeaders
76134         };
76135     },
76136
76137     
76138     onLockedGridAfterLayout: function() {
76139         var me         = this,
76140             lockedView = me.lockedGrid.getView();
76141         lockedView.on({
76142             beforerefresh: me.destroySpacer,
76143             scope: me
76144         });
76145     },
76146
76147     
76148     onLockedHeaderMove: function() {
76149         if (this.syncRowHeight) {
76150             this.onNormalGridAfterRefresh();
76151         }
76152     },
76153
76154     
76155     onNormalHeaderMove: function() {
76156         if (this.syncRowHeight) {
76157             this.onLockedGridAfterRefresh();
76158         }
76159     },
76160
76161     
76162     
76163     getSpacerEl: function() {
76164         var me   = this,
76165             w,
76166             view,
76167             el;
76168
76169         if (!me.spacerEl) {
76170             
76171             
76172             w    = Ext.getScrollBarWidth() + (Ext.isIE ? 2 : 0);
76173             view = me.lockedGrid.getView();
76174             el   = view.el;
76175
76176             me.spacerEl = Ext.DomHelper.append(el, {
76177                 cls: me.spacerHidden ? (Ext.baseCSSPrefix + 'hidden') : '',
76178                 style: 'height: ' + w + 'px;'
76179             }, true);
76180         }
76181         return me.spacerEl;
76182     },
76183
76184     destroySpacer: function() {
76185         var me = this;
76186         if (me.spacerEl) {
76187             me.spacerEl.destroy();
76188             delete me.spacerEl;
76189         }
76190     },
76191
76192     
76193     onLockedGridAfterRefresh: function() {
76194         var me     = this,
76195             view   = me.lockedGrid.getView(),
76196             el     = view.el,
76197             rowEls = el.query(view.getItemSelector()),
76198             ln     = rowEls.length,
76199             i = 0;
76200
76201         
76202         me.lockedHeights = [];
76203
76204         for (; i < ln; i++) {
76205             me.lockedHeights[i] = rowEls[i].clientHeight;
76206         }
76207         me.syncRowHeights();
76208     },
76209
76210     
76211     onNormalGridAfterRefresh: function() {
76212         var me     = this,
76213             view   = me.normalGrid.getView(),
76214             el     = view.el,
76215             rowEls = el.query(view.getItemSelector()),
76216             ln     = rowEls.length,
76217             i = 0;
76218
76219         
76220         me.normalHeights = [];
76221
76222         for (; i < ln; i++) {
76223             me.normalHeights[i] = rowEls[i].clientHeight;
76224         }
76225         me.syncRowHeights();
76226     },
76227
76228     
76229     onLockedGridAfterUpdate: function(record, index, node) {
76230         this.lockedHeights[index] = node.clientHeight;
76231         this.syncRowHeights();
76232     },
76233
76234     
76235     onNormalGridAfterUpdate: function(record, index, node) {
76236         this.normalHeights[index] = node.clientHeight;
76237         this.syncRowHeights();
76238     },
76239
76240     
76241     
76242     syncRowHeights: function() {
76243         var me = this,
76244             lockedHeights = me.lockedHeights,
76245             normalHeights = me.normalHeights,
76246             calcHeights   = [],
76247             ln = lockedHeights.length,
76248             i  = 0,
76249             lockedView, normalView,
76250             lockedRowEls, normalRowEls,
76251             vertScroller = me.getVerticalScroller(),
76252             scrollTop;
76253
76254         
76255         
76256         if (lockedHeights.length && normalHeights.length) {
76257             lockedView = me.lockedGrid.getView();
76258             normalView = me.normalGrid.getView();
76259             lockedRowEls = lockedView.el.query(lockedView.getItemSelector());
76260             normalRowEls = normalView.el.query(normalView.getItemSelector());
76261
76262             
76263             for (; i < ln; i++) {
76264                 
76265                 if (!isNaN(lockedHeights[i]) && !isNaN(normalHeights[i])) {
76266                     if (lockedHeights[i] > normalHeights[i]) {
76267                         Ext.fly(normalRowEls[i]).setHeight(lockedHeights[i]);
76268                     } else if (lockedHeights[i] < normalHeights[i]) {
76269                         Ext.fly(lockedRowEls[i]).setHeight(normalHeights[i]);
76270                     }
76271                 }
76272             }
76273
76274             
76275             me.normalGrid.invalidateScroller();
76276
76277             
76278             
76279             if (vertScroller && vertScroller.setViewScrollTop) {
76280                 vertScroller.setViewScrollTop(me.virtualScrollTop);
76281             } else {
76282                 
76283                 
76284                 
76285                 scrollTop = normalView.el.dom.scrollTop;
76286                 normalView.el.dom.scrollTop = scrollTop;
76287                 lockedView.el.dom.scrollTop = scrollTop;
76288             }
76289
76290             
76291             me.lockedHeights = [];
76292             me.normalHeights = [];
76293         }
76294     },
76295
76296     
76297     onScrollerShow: function(scroller, direction) {
76298         if (direction === 'horizontal') {
76299             this.spacerHidden = false;
76300             this.getSpacerEl().removeCls(Ext.baseCSSPrefix + 'hidden');
76301         }
76302     },
76303
76304     
76305     onScrollerHide: function(scroller, direction) {
76306         if (direction === 'horizontal') {
76307             this.spacerHidden = true;
76308             if (this.spacerEl) {
76309                 this.spacerEl.addCls(Ext.baseCSSPrefix + 'hidden');
76310             }
76311         }
76312     },
76313
76314
76315     
76316     modifyHeaderCt: function() {
76317         var me = this;
76318         me.lockedGrid.headerCt.getMenuItems = me.getMenuItems(true);
76319         me.normalGrid.headerCt.getMenuItems = me.getMenuItems(false);
76320     },
76321
76322     onUnlockMenuClick: function() {
76323         this.unlock();
76324     },
76325
76326     onLockMenuClick: function() {
76327         this.lock();
76328     },
76329
76330     getMenuItems: function(locked) {
76331         var me            = this,
76332             unlockText    = me.unlockText,
76333             lockText      = me.lockText,
76334             unlockCls     = Ext.baseCSSPrefix + 'hmenu-unlock',
76335             lockCls       = Ext.baseCSSPrefix + 'hmenu-lock',
76336             unlockHandler = Ext.Function.bind(me.onUnlockMenuClick, me),
76337             lockHandler   = Ext.Function.bind(me.onLockMenuClick, me);
76338
76339         
76340         return function() {
76341             var o = Ext.grid.header.Container.prototype.getMenuItems.call(this);
76342             o.push('-',{
76343                 cls: unlockCls,
76344                 text: unlockText,
76345                 handler: unlockHandler,
76346                 disabled: !locked
76347             });
76348             o.push({
76349                 cls: lockCls,
76350                 text: lockText,
76351                 handler: lockHandler,
76352                 disabled: locked
76353             });
76354             return o;
76355         };
76356     },
76357
76358     
76359     
76360     lock: function(activeHd, toIdx) {
76361         var me         = this,
76362             normalGrid = me.normalGrid,
76363             lockedGrid = me.lockedGrid,
76364             normalHCt  = normalGrid.headerCt,
76365             lockedHCt  = lockedGrid.headerCt;
76366
76367         activeHd = activeHd || normalHCt.getMenu().activeHeader;
76368
76369         
76370         
76371         if (activeHd.flex) {
76372             activeHd.width = activeHd.getWidth();
76373             delete activeHd.flex;
76374         }
76375
76376         normalHCt.remove(activeHd, false);
76377         lockedHCt.suspendLayout = true;
76378         activeHd.locked = true;
76379         if (Ext.isDefined(toIdx)) {
76380             lockedHCt.insert(toIdx, activeHd);
76381         } else {
76382             lockedHCt.add(activeHd);
76383         }
76384         lockedHCt.suspendLayout = false;
76385         me.syncLockedSection();
76386
76387         me.fireEvent('lockcolumn', me, activeHd);
76388     },
76389
76390     syncLockedSection: function() {
76391         var me = this;
76392         me.syncLockedWidth();
76393         me.lockedGrid.getView().refresh();
76394         me.normalGrid.getView().refresh();
76395     },
76396
76397     
76398     
76399     syncLockedWidth: function() {
76400         var me = this,
76401             width = me.lockedGrid.headerCt.getFullWidth(true);
76402         me.lockedGrid.setWidth(width+1); 
76403         me.doComponentLayout();
76404     },
76405
76406     onLockedHeaderResize: function() {
76407         this.syncLockedWidth();
76408     },
76409
76410     onLockedHeaderHide: function() {
76411         this.syncLockedWidth();
76412     },
76413
76414     onLockedHeaderShow: function() {
76415         this.syncLockedWidth();
76416     },
76417
76418     onLockedHeaderSortChange: function(headerCt, header, sortState) {
76419         if (sortState) {
76420             
76421             
76422             this.normalGrid.headerCt.clearOtherSortStates(null, true);
76423         }
76424     },
76425
76426     onNormalHeaderSortChange: function(headerCt, header, sortState) {
76427         if (sortState) {
76428             
76429             
76430             this.lockedGrid.headerCt.clearOtherSortStates(null, true);
76431         }
76432     },
76433
76434     
76435     
76436     unlock: function(activeHd, toIdx) {
76437         var me         = this,
76438             normalGrid = me.normalGrid,
76439             lockedGrid = me.lockedGrid,
76440             normalHCt  = normalGrid.headerCt,
76441             lockedHCt  = lockedGrid.headerCt;
76442
76443         if (!Ext.isDefined(toIdx)) {
76444             toIdx = 0;
76445         }
76446         activeHd = activeHd || lockedHCt.getMenu().activeHeader;
76447
76448         lockedHCt.remove(activeHd, false);
76449         me.syncLockedWidth();
76450         me.lockedGrid.getView().refresh();
76451         activeHd.locked = false;
76452         normalHCt.insert(toIdx, activeHd);
76453         me.normalGrid.getView().refresh();
76454
76455         me.fireEvent('unlockcolumn', me, activeHd);
76456     },
76457
76458     applyColumnsState: function (columns) {
76459         var me = this,
76460             lockedGrid = me.lockedGrid,
76461             lockedHeaderCt = lockedGrid.headerCt,
76462             normalHeaderCt = me.normalGrid.headerCt,
76463             lockedCols = lockedHeaderCt.items,
76464             normalCols = normalHeaderCt.items,
76465             existing,
76466             locked = [],
76467             normal = [],
76468             lockedDefault,
76469             lockedWidth = 1;
76470
76471         Ext.each(columns, function (col) {
76472             function matches (item) {
76473                 return item.headerId == col.id;
76474             }
76475
76476             lockedDefault = true;
76477             if (!(existing = lockedCols.findBy(matches))) {
76478                 existing = normalCols.findBy(matches);
76479                 lockedDefault = false;
76480             }
76481
76482             if (existing) {
76483                 if (existing.applyColumnState) {
76484                     existing.applyColumnState(col);
76485                 }
76486                 if (!Ext.isDefined(existing.locked)) {
76487                     existing.locked = lockedDefault;
76488                 }
76489                 if (existing.locked) {
76490                     locked.push(existing);
76491                     if (!existing.hidden && Ext.isNumber(existing.width)) {
76492                         lockedWidth += existing.width;
76493                     }
76494                 } else {
76495                     normal.push(existing);
76496                 }
76497             }
76498         });
76499
76500         
76501         if (locked.length + normal.length == lockedCols.getCount() + normalCols.getCount()) {
76502             lockedHeaderCt.removeAll(false);
76503             normalHeaderCt.removeAll(false);
76504
76505             lockedHeaderCt.add(locked);
76506             normalHeaderCt.add(normal);
76507
76508             lockedGrid.setWidth(lockedWidth);
76509         }
76510     },
76511
76512     getColumnsState: function () {
76513         var me = this,
76514             locked = me.lockedGrid.headerCt.getColumnsState(),
76515             normal = me.normalGrid.headerCt.getColumnsState();
76516
76517         return locked.concat(normal);
76518     },
76519
76520     
76521     reconfigureLockable: function(store, columns) {
76522         var me = this,
76523             lockedGrid = me.lockedGrid,
76524             normalGrid = me.normalGrid;
76525
76526         if (columns) {
76527             lockedGrid.headerCt.suspendLayout = true;
76528             normalGrid.headerCt.suspendLayout = true;
76529             lockedGrid.headerCt.removeAll();
76530             normalGrid.headerCt.removeAll();
76531
76532             columns = me.processColumns(columns);
76533             lockedGrid.setWidth(columns.lockedWidth);
76534             lockedGrid.headerCt.add(columns.locked);
76535             normalGrid.headerCt.add(columns.normal);
76536         }
76537
76538         if (store) {
76539             store = Ext.data.StoreManager.lookup(store);
76540             me.store = store;
76541             lockedGrid.bindStore(store);
76542             normalGrid.bindStore(store);
76543         } else {
76544             lockedGrid.getView().refresh();
76545             normalGrid.getView().refresh();
76546         }
76547
76548         if (columns) {
76549             lockedGrid.headerCt.suspendLayout = false;
76550             normalGrid.headerCt.suspendLayout = false;
76551             lockedGrid.headerCt.forceComponentLayout();
76552             normalGrid.headerCt.forceComponentLayout();
76553         }
76554     }
76555 });
76556
76557
76558 Ext.define('Ext.grid.Scroller', {
76559     extend: 'Ext.Component',
76560     alias: 'widget.gridscroller',
76561     weight: 110,
76562     baseCls: Ext.baseCSSPrefix + 'scroller',
76563     focusable: false,
76564     reservedSpace: 0,
76565
76566     renderTpl: [
76567         '<div class="' + Ext.baseCSSPrefix + 'scroller-ct" id="{baseId}_ct">',
76568             '<div class="' + Ext.baseCSSPrefix + 'stretcher" id="{baseId}_stretch"></div>',
76569         '</div>'
76570     ],
76571
76572     initComponent: function() {
76573         var me       = this,
76574             dock     = me.dock,
76575             cls      = Ext.baseCSSPrefix + 'scroller-vertical';
76576
76577         me.offsets = {bottom: 0};
76578         me.scrollProp = 'scrollTop';
76579         me.vertical = true;
76580         me.sizeProp = 'width';
76581
76582         if (dock === 'top' || dock === 'bottom') {
76583             cls = Ext.baseCSSPrefix + 'scroller-horizontal';
76584             me.sizeProp = 'height';
76585             me.scrollProp = 'scrollLeft';
76586             me.vertical = false;
76587             me.weight += 5;
76588         }
76589
76590         me.cls += (' ' + cls);
76591
76592         Ext.applyIf(me.renderSelectors, {
76593             stretchEl: '.' + Ext.baseCSSPrefix + 'stretcher',
76594             scrollEl: '.' + Ext.baseCSSPrefix + 'scroller-ct'
76595         });
76596         me.callParent();
76597     },
76598     
76599     ensureDimension: function(){
76600         var me = this,
76601             sizeProp = me.sizeProp;
76602             
76603         me[sizeProp] = me.scrollerSize = Ext.getScrollbarSize()[sizeProp];  
76604     },
76605
76606     initRenderData: function () {
76607         var me = this,
76608             ret = me.callParent(arguments) || {};
76609
76610         ret.baseId = me.id;
76611
76612         return ret;
76613     },
76614
76615     afterRender: function() {
76616         var me = this;
76617         me.callParent();
76618         
76619         me.mon(me.scrollEl, 'scroll', me.onElScroll, me);
76620         Ext.cache[me.el.id].skipGarbageCollection = true;
76621     },
76622
76623     onAdded: function(container) {
76624         
76625         this.ownerGrid = container;
76626         this.callParent(arguments);
76627     },
76628
76629     getSizeCalculation: function() {
76630         var me     = this,
76631             owner  = me.getPanel(),
76632             width  = 1,
76633             height = 1,
76634             view, tbl;
76635
76636         if (!me.vertical) {
76637             
76638             
76639             var items  = owner.query('tableview'),
76640                 center = items[1] || items[0];
76641
76642             if (!center) {
76643                 return false;
76644             }
76645             
76646             
76647             
76648             width = center.headerCt.getFullWidth();
76649
76650             if (Ext.isIEQuirks) {
76651                 width--;
76652             }
76653         } else {
76654             view = owner.down('tableview:not([lockableInjected])');
76655             if (!view || !view.el) {
76656                 return false;
76657             }
76658             tbl = view.el.child('table', true);
76659             if (!tbl) {
76660                 return false;
76661             }
76662
76663             
76664             
76665             height = tbl.offsetHeight;
76666         }
76667         if (isNaN(width)) {
76668             width = 1;
76669         }
76670         if (isNaN(height)) {
76671             height = 1;
76672         }
76673         return {
76674             width: width,
76675             height: height
76676         };
76677     },
76678
76679     invalidate: function(firstPass) {
76680         var me = this,
76681             stretchEl = me.stretchEl;
76682
76683         if (!stretchEl || !me.ownerCt) {
76684             return;
76685         }
76686
76687         var size  = me.getSizeCalculation(),
76688             scrollEl = me.scrollEl,
76689             elDom = scrollEl.dom,
76690             reservedSpace = me.reservedSpace,
76691             pos,
76692             extra = 5;
76693
76694         if (size) {
76695             stretchEl.setSize(size);
76696
76697             size = me.el.getSize(true);
76698
76699             if (me.vertical) {
76700                 size.width += extra;
76701                 size.height -= reservedSpace;
76702                 pos = 'left';
76703             } else {
76704                 size.width -= reservedSpace;
76705                 size.height += extra;
76706                 pos = 'top';
76707             }
76708
76709             scrollEl.setSize(size);
76710             elDom.style[pos] = (-extra) + 'px';
76711
76712             
76713             
76714             elDom.scrollTop = elDom.scrollTop;
76715         }
76716     },
76717
76718     afterComponentLayout: function() {
76719         this.callParent(arguments);
76720         this.invalidate();
76721     },
76722
76723     restoreScrollPos: function () {
76724         var me = this,
76725             el = this.scrollEl,
76726             elDom = el && el.dom;
76727
76728         if (me._scrollPos !== null && elDom) {
76729             elDom[me.scrollProp] = me._scrollPos;
76730             me._scrollPos = null;
76731         }
76732     },
76733
76734     setReservedSpace: function (reservedSpace) {
76735         var me = this;
76736         if (me.reservedSpace !== reservedSpace) {
76737             me.reservedSpace = reservedSpace;
76738             me.invalidate();
76739         }
76740     },
76741
76742     saveScrollPos: function () {
76743         var me = this,
76744             el = this.scrollEl,
76745             elDom = el && el.dom;
76746
76747         me._scrollPos = elDom ? elDom[me.scrollProp] : null;
76748     },
76749
76750     
76751     setScrollTop: function(scrollTop) {
76752         var el = this.scrollEl,
76753             elDom = el && el.dom;
76754
76755         if (elDom) {
76756             return elDom.scrollTop = Ext.Number.constrain(scrollTop, 0, elDom.scrollHeight - elDom.clientHeight);
76757         }
76758     },
76759
76760     
76761     setScrollLeft: function(scrollLeft) {
76762         var el = this.scrollEl,
76763             elDom = el && el.dom;
76764
76765         if (elDom) {
76766             return elDom.scrollLeft = Ext.Number.constrain(scrollLeft, 0, elDom.scrollWidth - elDom.clientWidth);
76767         }
76768     },
76769
76770     
76771     scrollByDeltaY: function(delta) {
76772         var el = this.scrollEl,
76773             elDom = el && el.dom;
76774
76775         if (elDom) {
76776             return this.setScrollTop(elDom.scrollTop + delta);
76777         }
76778     },
76779
76780     
76781     scrollByDeltaX: function(delta) {
76782         var el = this.scrollEl,
76783             elDom = el && el.dom;
76784
76785         if (elDom) {
76786             return this.setScrollLeft(elDom.scrollLeft + delta);
76787         }
76788     },
76789
76790
76791     
76792     scrollToTop : function(){
76793         this.setScrollTop(0);
76794     },
76795
76796     
76797     onElScroll: function(event, target) {
76798         this.fireEvent('bodyscroll', event, target);
76799     },
76800
76801     getPanel: function() {
76802         var me = this;
76803         if (!me.panel) {
76804             me.panel = this.up('[scrollerOwner]');
76805         }
76806         return me.panel;
76807     }
76808 });
76809
76810
76811
76812 Ext.define('Ext.grid.PagingScroller', {
76813     extend: 'Ext.grid.Scroller',
76814     alias: 'widget.paginggridscroller',
76815     
76816     
76817     
76818     
76819     
76820     
76821     
76822     percentageFromEdge: 0.35,
76823
76824     
76825     scrollToLoadBuffer: 200,
76826
76827     activePrefetch: true,
76828
76829     chunkSize: 50,
76830     snapIncrement: 25,
76831
76832     syncScroll: true,
76833
76834     initComponent: function() {
76835         var me = this,
76836             ds = me.store;
76837
76838         ds.on('guaranteedrange', me.onGuaranteedRange, me);
76839         me.callParent(arguments);
76840     },
76841
76842     onGuaranteedRange: function(range, start, end) {
76843         var me = this,
76844             ds = me.store,
76845             rs;
76846         
76847         if (range.length && me.visibleStart < range[0].index) {
76848             return;
76849         }
76850
76851         ds.loadRecords(range);
76852
76853         if (!me.firstLoad) {
76854             if (me.rendered) {
76855                 me.invalidate();
76856             } else {
76857                 me.on('afterrender', me.invalidate, me, {single: true});
76858             }
76859             me.firstLoad = true;
76860         } else {
76861             
76862             
76863             if (me.scrollEl && me.scrollEl.dom && me.scrollEl.dom.scrollHeight) {
76864                 me.syncTo();
76865             }
76866         }
76867     },
76868
76869     syncTo: function() {
76870         var me            = this,
76871             pnl           = me.getPanel(),
76872             store         = pnl.store,
76873             scrollerElDom = this.scrollEl.dom,
76874             rowOffset     = me.visibleStart - store.guaranteedStart,
76875             scrollBy      = rowOffset * me.rowHeight,
76876             scrollHeight  = scrollerElDom.scrollHeight,
76877             clientHeight  = scrollerElDom.clientHeight,
76878             scrollTop     = scrollerElDom.scrollTop,
76879             useMaximum;
76880             
76881
76882         
76883         
76884         if (Ext.isIE9 && Ext.isStrict) {
76885             clientHeight = scrollerElDom.offsetHeight + 2;
76886         }
76887
76888         
76889         
76890         useMaximum = (scrollHeight - clientHeight - scrollTop <= 0);
76891         this.setViewScrollTop(scrollBy, useMaximum);
76892     },
76893
76894     getPageData : function(){
76895         var panel = this.getPanel(),
76896             store = panel.store,
76897             totalCount = store.getTotalCount();
76898
76899         return {
76900             total : totalCount,
76901             currentPage : store.currentPage,
76902             pageCount: Math.ceil(totalCount / store.pageSize),
76903             fromRecord: ((store.currentPage - 1) * store.pageSize) + 1,
76904             toRecord: Math.min(store.currentPage * store.pageSize, totalCount)
76905         };
76906     },
76907
76908     onElScroll: function(e, t) {
76909         var me = this,
76910             panel = me.getPanel(),
76911             store = panel.store,
76912             pageSize = store.pageSize,
76913             guaranteedStart = store.guaranteedStart,
76914             guaranteedEnd = store.guaranteedEnd,
76915             totalCount = store.getTotalCount(),
76916             numFromEdge = Math.ceil(me.percentageFromEdge * pageSize),
76917             position = t.scrollTop,
76918             visibleStart = Math.floor(position / me.rowHeight),
76919             view = panel.down('tableview'),
76920             viewEl = view.el,
76921             visibleHeight = viewEl.getHeight(),
76922             visibleAhead = Math.ceil(visibleHeight / me.rowHeight),
76923             visibleEnd = visibleStart + visibleAhead,
76924             prevPage = Math.floor(visibleStart / pageSize),
76925             nextPage = Math.floor(visibleEnd / pageSize) + 2,
76926             lastPage = Math.ceil(totalCount / pageSize),
76927             snap = me.snapIncrement,
76928             requestStart = Math.floor(visibleStart / snap) * snap,
76929             requestEnd = requestStart + pageSize - 1,
76930             activePrefetch = me.activePrefetch;
76931
76932         me.visibleStart = visibleStart;
76933         me.visibleEnd = visibleEnd;
76934         
76935         
76936         me.syncScroll = true;
76937         if (totalCount >= pageSize) {
76938             
76939             if (requestEnd > totalCount - 1) {
76940                 me.cancelLoad();
76941                 if (store.rangeSatisfied(totalCount - pageSize, totalCount - 1)) {
76942                     me.syncScroll = true;
76943                 }
76944                 store.guaranteeRange(totalCount - pageSize, totalCount - 1);
76945             
76946             } else if (visibleStart <= guaranteedStart || visibleEnd > guaranteedEnd) {
76947                 if (visibleStart <= guaranteedStart) {
76948                     
76949                     requestStart -= snap;
76950                     requestEnd -= snap;
76951                     
76952                     if (requestStart < 0) {
76953                         requestStart = 0;
76954                         requestEnd = pageSize;
76955                     }
76956                 }
76957                 if (store.rangeSatisfied(requestStart, requestEnd)) {
76958                     me.cancelLoad();
76959                     store.guaranteeRange(requestStart, requestEnd);
76960                 } else {
76961                     store.mask();
76962                     me.attemptLoad(requestStart, requestEnd);
76963                 }
76964                 
76965                 me.syncScroll = false;
76966             } else if (activePrefetch && visibleStart < (guaranteedStart + numFromEdge) && prevPage > 0) {
76967                 me.syncScroll = true;
76968                 store.prefetchPage(prevPage);
76969             } else if (activePrefetch && visibleEnd > (guaranteedEnd - numFromEdge) && nextPage < lastPage) {
76970                 me.syncScroll = true;
76971                 store.prefetchPage(nextPage);
76972             }
76973         }
76974
76975         if (me.syncScroll) {
76976             me.syncTo();
76977         }
76978     },
76979
76980     getSizeCalculation: function() {
76981         
76982         
76983         var me     = this,
76984             owner  = me.ownerGrid,
76985             view   = owner.getView(),
76986             store  = me.store,
76987             dock   = me.dock,
76988             elDom  = me.el.dom,
76989             width  = 1,
76990             height = 1;
76991
76992         if (!me.rowHeight) {
76993             me.rowHeight = view.el.down(view.getItemSelector()).getHeight(false, true);
76994         }
76995
76996         
76997         height = store[(!store.remoteFilter && store.isFiltered()) ? 'getCount' : 'getTotalCount']() * me.rowHeight;
76998
76999         if (isNaN(width)) {
77000             width = 1;
77001         }
77002         if (isNaN(height)) {
77003             height = 1;
77004         }
77005         return {
77006             width: width,
77007             height: height
77008         };
77009     },
77010
77011     attemptLoad: function(start, end) {
77012         var me = this;
77013         if (!me.loadTask) {
77014             me.loadTask = Ext.create('Ext.util.DelayedTask', me.doAttemptLoad, me, []);
77015         }
77016         me.loadTask.delay(me.scrollToLoadBuffer, me.doAttemptLoad, me, [start, end]);
77017     },
77018
77019     cancelLoad: function() {
77020         if (this.loadTask) {
77021             this.loadTask.cancel();
77022         }
77023     },
77024
77025     doAttemptLoad:  function(start, end) {
77026         var store = this.getPanel().store;
77027         store.guaranteeRange(start, end);
77028     },
77029
77030     setViewScrollTop: function(scrollTop, useMax) {
77031         var me = this,
77032             owner = me.getPanel(),
77033             items = owner.query('tableview'),
77034             i = 0,
77035             len = items.length,
77036             center,
77037             centerEl,
77038             calcScrollTop,
77039             maxScrollTop,
77040             scrollerElDom = me.el.dom;
77041
77042         owner.virtualScrollTop = scrollTop;
77043
77044         center = items[1] || items[0];
77045         centerEl = center.el.dom;
77046
77047         maxScrollTop = ((owner.store.pageSize * me.rowHeight) - centerEl.clientHeight);
77048         calcScrollTop = (scrollTop % ((owner.store.pageSize * me.rowHeight) + 1));
77049         if (useMax) {
77050             calcScrollTop = maxScrollTop;
77051         }
77052         if (calcScrollTop > maxScrollTop) {
77053             
77054             return;
77055             
77056         }
77057         for (; i < len; i++) {
77058             items[i].el.dom.scrollTop = calcScrollTop;
77059         }
77060     }
77061 });
77062
77063
77064 Ext.define('Ext.panel.Table', {
77065     extend: 'Ext.panel.Panel',
77066
77067     alias: 'widget.tablepanel',
77068
77069     uses: [
77070         'Ext.selection.RowModel',
77071         'Ext.grid.Scroller',
77072         'Ext.grid.header.Container',
77073         'Ext.grid.Lockable'
77074     ],
77075
77076     extraBaseCls: Ext.baseCSSPrefix + 'grid',
77077     extraBodyCls: Ext.baseCSSPrefix + 'grid-body',
77078
77079     layout: 'fit',
77080     
77081     hasView: false,
77082
77083     
77084     
77085     viewType: null,
77086
77087     
77088
77089     
77090
77091     
77092     selType: 'rowmodel',
77093
77094     
77095
77096     
77097
77098     
77099
77100     
77101
77102     
77103     scrollDelta: 40,
77104
77105     
77106     scroll: true,
77107
77108     
77109
77110     
77111
77112     
77113
77114     
77115
77116     
77117
77118      deferRowRender: true,
77119      
77120     
77121     sortableColumns: true,
77122
77123     
77124     enableLocking: false,
77125
77126     verticalScrollDock: 'right',
77127     verticalScrollerType: 'gridscroller',
77128
77129     horizontalScrollerPresentCls: Ext.baseCSSPrefix + 'horizontal-scroller-present',
77130     verticalScrollerPresentCls: Ext.baseCSSPrefix + 'vertical-scroller-present',
77131
77132     
77133     
77134     scrollerOwner: true,
77135
77136     invalidateScrollerOnRefresh: true,
77137
77138     
77139     enableColumnMove: true,
77140
77141     
77142     enableColumnResize: true,
77143
77144     
77145     enableColumnHide: true,
77146
77147     initComponent: function() {
77148
77149         var me          = this,
77150             scroll      = me.scroll,
77151             vertical    = false,
77152             horizontal  = false,
77153             headerCtCfg = me.columns || me.colModel,
77154             i           = 0,
77155             view,
77156             border = me.border;
77157
77158         if (me.hideHeaders) {
77159             border = false;
77160         }
77161
77162         
77163         me.store = Ext.data.StoreManager.lookup(me.store || 'ext-empty-store');
77164
77165         
77166         
77167         if (headerCtCfg instanceof Ext.grid.header.Container) {
77168             me.headerCt = headerCtCfg;
77169             me.headerCt.border = border;
77170             me.columns = me.headerCt.items.items;
77171         } else {
77172             if (Ext.isArray(headerCtCfg)) {
77173                 headerCtCfg = {
77174                     items: headerCtCfg,
77175                     border: border
77176                 };
77177             }
77178             Ext.apply(headerCtCfg, {
77179                 forceFit: me.forceFit,
77180                 sortable: me.sortableColumns,
77181                 enableColumnMove: me.enableColumnMove,
77182                 enableColumnResize: me.enableColumnResize,
77183                 enableColumnHide: me.enableColumnHide,
77184                 border:  border
77185             });
77186             me.columns = headerCtCfg.items;
77187
77188              
77189              
77190              if (me.enableLocking || Ext.ComponentQuery.query('{locked !== undefined}{processed != true}', me.columns).length) {
77191                  me.self.mixin('lockable', Ext.grid.Lockable);
77192                  me.injectLockable();
77193              }
77194         }
77195
77196         me.addEvents(
77197             
77198             'reconfigure',
77199             
77200             'viewready',
77201             
77202             'scrollerhide',
77203             
77204             'scrollershow'
77205         );
77206
77207         me.bodyCls = me.bodyCls || '';
77208         me.bodyCls += (' ' + me.extraBodyCls);
77209         
77210         me.cls = me.cls || '';
77211         me.cls += (' ' + me.extraBaseCls);
77212
77213         
77214         delete me.autoScroll;
77215
77216         
77217         
77218         if (!me.hasView) {
77219
77220             
77221             
77222             if (!me.headerCt) {
77223                 me.headerCt = Ext.create('Ext.grid.header.Container', headerCtCfg);
77224             }
77225
77226             
77227             me.columns = me.headerCt.items.items;
77228
77229             if (me.hideHeaders) {
77230                 me.headerCt.height = 0;
77231                 me.headerCt.border = false;
77232                 me.headerCt.addCls(Ext.baseCSSPrefix + 'grid-header-ct-hidden');
77233                 me.addCls(Ext.baseCSSPrefix + 'grid-header-hidden');
77234                 
77235                 
77236                 if (Ext.isIEQuirks) {
77237                     me.headerCt.style = {
77238                         display: 'none'
77239                     };
77240                 }
77241             }
77242
77243             
77244             if (scroll === true || scroll === 'both') {
77245                 vertical = horizontal = true;
77246             } else if (scroll === 'horizontal') {
77247                 horizontal = true;
77248             } else if (scroll === 'vertical') {
77249                 vertical = true;
77250             
77251             } else {
77252                 me.headerCt.availableSpaceOffset = 0;
77253             }
77254
77255             if (vertical) {
77256                 me.verticalScroller = Ext.ComponentManager.create(me.initVerticalScroller());
77257                 me.mon(me.verticalScroller, {
77258                     bodyscroll: me.onVerticalScroll,
77259                     scope: me
77260                 });
77261             }
77262
77263             if (horizontal) {
77264                 me.horizontalScroller = Ext.ComponentManager.create(me.initHorizontalScroller());
77265                 me.mon(me.horizontalScroller, {
77266                     bodyscroll: me.onHorizontalScroll,
77267                     scope: me
77268                 });
77269             }
77270
77271             me.headerCt.on('resize', me.onHeaderResize, me);
77272             me.relayHeaderCtEvents(me.headerCt);
77273             me.features = me.features || [];
77274             if (!Ext.isArray(me.features)) {
77275                 me.features = [me.features];
77276             }
77277             me.dockedItems = me.dockedItems || [];
77278             me.dockedItems.unshift(me.headerCt);
77279             me.viewConfig = me.viewConfig || {};
77280             me.viewConfig.invalidateScrollerOnRefresh = me.invalidateScrollerOnRefresh;
77281
77282             
77283             
77284             view = me.getView();
77285
77286             view.on({
77287                 afterrender: function () {
77288                     
77289                     view.el.scroll = Ext.Function.bind(me.elScroll, me);
77290                     
77291                     
77292                     me.mon(view.el, {
77293                         mousewheel: me.onMouseWheel,
77294                         scope: me
77295                     });
77296                 },
77297                 single: true
77298             });
77299             me.items = [view];
77300             me.hasView = true;
77301
77302             me.mon(view.store, {
77303                 load: me.onStoreLoad,
77304                 scope: me
77305             });
77306             me.mon(view, {
77307                 viewReady: me.onViewReady,
77308                 resize: me.onViewResize,
77309                 refresh: {
77310                     fn: me.onViewRefresh,
77311                     scope: me,
77312                     buffer: 50
77313                 },
77314                 scope: me
77315             });
77316             this.relayEvents(view, [
77317                 
77318                 'beforeitemmousedown',
77319                 
77320                 'beforeitemmouseup',
77321                 
77322                 'beforeitemmouseenter',
77323                 
77324                 'beforeitemmouseleave',
77325                 
77326                 'beforeitemclick',
77327                 
77328                 'beforeitemdblclick',
77329                 
77330                 'beforeitemcontextmenu',
77331                 
77332                 'itemmousedown',
77333                 
77334                 'itemmouseup',
77335                 
77336                 'itemmouseenter',
77337                 
77338                 'itemmouseleave',
77339                 
77340                 'itemclick',
77341                 
77342                 'itemdblclick',
77343                 
77344                 'itemcontextmenu',
77345                 
77346                 'beforecontainermousedown',
77347                 
77348                 'beforecontainermouseup',
77349                 
77350                 'beforecontainermouseover',
77351                 
77352                 'beforecontainermouseout',
77353                 
77354                 'beforecontainerclick',
77355                 
77356                 'beforecontainerdblclick',
77357                 
77358                 'beforecontainercontextmenu',
77359                 
77360                 'containermouseup',
77361                 
77362                 'containermouseover',
77363                 
77364                 'containermouseout',
77365                 
77366                 'containerclick',
77367                 
77368                 'containerdblclick',
77369                 
77370                 'containercontextmenu',
77371                 
77372                 'selectionchange',
77373                 
77374                 'beforeselect',
77375                 
77376                 'select',
77377                 
77378                 'beforedeselect',
77379                 
77380                 'deselect'
77381             ]);
77382         }
77383
77384         me.callParent(arguments);
77385     },
77386     
77387     onRender: function(){
77388         var vScroll = this.verticalScroller,
77389             hScroll = this.horizontalScroller;
77390
77391         if (vScroll) {
77392             vScroll.ensureDimension();
77393         }
77394         if (hScroll) {
77395             hScroll.ensureDimension();
77396         }
77397         this.callParent(arguments);    
77398     },
77399
77400     
77401     initStateEvents: function(){
77402         var events = this.stateEvents;
77403         
77404         Ext.each(['columnresize', 'columnmove', 'columnhide', 'columnshow', 'sortchange'], function(event){
77405             if (Ext.Array.indexOf(events, event)) {
77406                 events.push(event);
77407             }
77408         });
77409         this.callParent();
77410     },
77411
77412     
77413     initHorizontalScroller: function () {
77414         var me = this,
77415             ret = {
77416                 xtype: 'gridscroller',
77417                 dock: 'bottom',
77418                 section: me,
77419                 store: me.store
77420             };
77421
77422         return ret;
77423     },
77424
77425     
77426     initVerticalScroller: function () {
77427         var me = this,
77428             ret = me.verticalScroller || {};
77429
77430         Ext.applyIf(ret, {
77431             xtype: me.verticalScrollerType,
77432             dock: me.verticalScrollDock,
77433             store: me.store
77434         });
77435
77436         return ret;
77437     },
77438
77439     relayHeaderCtEvents: function (headerCt) {
77440         this.relayEvents(headerCt, [
77441             
77442             'columnresize',
77443             
77444             'columnmove',
77445             
77446             'columnhide',
77447             
77448             'columnshow',
77449             
77450             'sortchange'
77451         ]);
77452     },
77453
77454     getState: function(){
77455         var me = this,
77456             state = me.callParent(),
77457             sorter = me.store.sorters.first();
77458
77459         state.columns = (me.headerCt || me).getColumnsState();
77460
77461         if (sorter) {
77462             state.sort = {
77463                 property: sorter.property,
77464                 direction: sorter.direction
77465             };
77466         }
77467
77468         return state;
77469     },
77470
77471     applyState: function(state) {
77472         var me = this,
77473             sorter = state.sort,
77474             store = me.store,
77475             columns = state.columns;
77476
77477         delete state.columns;
77478
77479         
77480         
77481         me.callParent(arguments);
77482
77483         if (columns) {
77484             (me.headerCt || me).applyColumnsState(columns);
77485         }
77486
77487         if (sorter) {
77488             if (store.remoteSort) {
77489                 store.sorters.add(Ext.create('Ext.util.Sorter', {
77490                     property: sorter.property,
77491                     direction: sorter.direction
77492                 }));
77493             }
77494             else {
77495                 store.sort(sorter.property, sorter.direction);
77496             }
77497         }
77498     },
77499
77500     
77501     getStore: function(){
77502         return this.store;
77503     },
77504
77505     
77506     getView: function() {
77507         var me = this,
77508             sm;
77509
77510         if (!me.view) {
77511             sm = me.getSelectionModel();
77512             me.view = me.createComponent(Ext.apply({}, me.viewConfig, {
77513                 deferInitialRefresh: me.deferRowRender,
77514                 xtype: me.viewType,
77515                 store: me.store,
77516                 headerCt: me.headerCt,
77517                 selModel: sm,
77518                 features: me.features,
77519                 panel: me
77520             }));
77521             me.mon(me.view, {
77522                 uievent: me.processEvent,
77523                 scope: me
77524             });
77525             sm.view = me.view;
77526             me.headerCt.view = me.view;
77527             me.relayEvents(me.view, ['cellclick', 'celldblclick']);
77528         }
77529         return me.view;
77530     },
77531
77532     
77533     setAutoScroll: Ext.emptyFn,
77534
77535     
77536     
77537     
77538     elScroll: function(direction, distance, animate) {
77539         var me = this,
77540             scroller;
77541
77542         if (direction === "up" || direction === "left") {
77543             distance = -distance;
77544         }
77545         
77546         if (direction === "down" || direction === "up") {
77547             scroller = me.getVerticalScroller();
77548             
77549             
77550             if (scroller) {
77551                 scroller.scrollByDeltaY(distance);
77552             }
77553         } else {
77554             scroller = me.getHorizontalScroller();
77555             
77556             
77557             if (scroller) {
77558                 scroller.scrollByDeltaX(distance);
77559             }
77560         }
77561     },
77562
77563     
77564     processEvent: function(type, view, cell, recordIndex, cellIndex, e) {
77565         var me = this,
77566             header;
77567
77568         if (cellIndex !== -1) {
77569             header = me.headerCt.getGridColumns()[cellIndex];
77570             return header.processEvent.apply(header, arguments);
77571         }
77572     },
77573
77574     
77575     determineScrollbars: function() {
77576         
77577         if (this.determineScrollbarsRunning) {
77578             return;
77579         }
77580         this.determineScrollbarsRunning = true;
77581         var me = this,
77582             view = me.view,
77583             box,
77584             tableEl,
77585             scrollWidth,
77586             clientWidth,
77587             scrollHeight,
77588             clientHeight,
77589             verticalScroller = me.verticalScroller,
77590             horizontalScroller = me.horizontalScroller,
77591             curScrollbars = (verticalScroller   && verticalScroller.ownerCt === me ? 1 : 0) |
77592                             (horizontalScroller && horizontalScroller.ownerCt === me ? 2 : 0),
77593             reqScrollbars = 0; 
77594
77595         
77596         if (!me.collapsed && view && view.viewReady) {
77597
77598             
77599             
77600             box = view.el.getSize();
77601
77602             clientWidth  = box.width  + ((curScrollbars & 1) ? verticalScroller.width : 0);
77603             clientHeight = box.height + ((curScrollbars & 2) ? horizontalScroller.height : 0);
77604
77605             
77606             
77607
77608             scrollWidth = (me.headerCt.query('[flex]').length && !me.headerCt.layout.tooNarrow) ? 0 : me.headerCt.getFullWidth();
77609
77610             
77611             if (verticalScroller && verticalScroller.el) {
77612                 scrollHeight = verticalScroller.getSizeCalculation().height;
77613             } else {
77614                 tableEl = view.el.child('table', true);
77615                 scrollHeight = tableEl ? tableEl.offsetHeight : 0;
77616             }
77617
77618             
77619             
77620             if (scrollHeight > clientHeight) {
77621                 reqScrollbars = 1;
77622
77623                 
77624                 if (horizontalScroller && ((clientWidth - scrollWidth) < verticalScroller.width)) {
77625                     reqScrollbars = 3;
77626                 }
77627             }
77628
77629             
77630             else {
77631                 
77632                 
77633                 if (scrollWidth > clientWidth) {
77634                     reqScrollbars = 2;
77635
77636                     
77637                     if (verticalScroller && ((clientHeight - scrollHeight) < horizontalScroller.height)) {
77638                         reqScrollbars = 3;
77639                     }
77640                 }
77641             }
77642
77643             
77644             if (reqScrollbars !== curScrollbars) {
77645
77646                 
77647                 me.suspendLayout = true;
77648                 if (reqScrollbars & 1) {
77649                     me.showVerticalScroller();
77650                 } else {
77651                     me.hideVerticalScroller();
77652                 }
77653                 if (reqScrollbars & 2) {
77654                     me.showHorizontalScroller();
77655                 } else {
77656                     me.hideHorizontalScroller();
77657                 }
77658                 me.suspendLayout = false;
77659
77660                 
77661                 me.doComponentLayout();
77662                 
77663                 me.getLayout().layout();
77664             }
77665         }
77666         delete me.determineScrollbarsRunning;
77667     },
77668
77669     onViewResize: function() {
77670         this.determineScrollbars();
77671     },
77672
77673     afterComponentLayout: function() {
77674         this.callParent(arguments);
77675         this.determineScrollbars();
77676         this.invalidateScroller();
77677     },
77678
77679     onHeaderResize: function() {
77680         if (!this.componentLayout.layoutBusy && this.view && this.view.rendered) {
77681             this.determineScrollbars();
77682             this.invalidateScroller();
77683         }
77684     },
77685
77686     afterCollapse: function() {
77687         var me = this;
77688         if (me.verticalScroller) {
77689             me.verticalScroller.saveScrollPos();
77690         }
77691         if (me.horizontalScroller) {
77692             me.horizontalScroller.saveScrollPos();
77693         }
77694         me.callParent(arguments);
77695     },
77696
77697     afterExpand: function() {
77698         var me = this;
77699         me.callParent(arguments);
77700         if (me.verticalScroller) {
77701             me.verticalScroller.restoreScrollPos();
77702         }
77703         if (me.horizontalScroller) {
77704             me.horizontalScroller.restoreScrollPos();
77705         }
77706     },
77707
77708     
77709     hideHorizontalScroller: function() {
77710         var me = this;
77711
77712         if (me.horizontalScroller && me.horizontalScroller.ownerCt === me) {
77713             me.verticalScroller.setReservedSpace(0);
77714             me.removeDocked(me.horizontalScroller, false);
77715             me.removeCls(me.horizontalScrollerPresentCls);
77716             me.fireEvent('scrollerhide', me.horizontalScroller, 'horizontal');
77717         }
77718
77719     },
77720
77721     
77722     showHorizontalScroller: function() {
77723         var me = this;
77724
77725         if (me.verticalScroller) {
77726             me.verticalScroller.setReservedSpace(Ext.getScrollbarSize().height - 1);
77727         }
77728         if (me.horizontalScroller && me.horizontalScroller.ownerCt !== me) {
77729             me.addDocked(me.horizontalScroller);
77730             me.addCls(me.horizontalScrollerPresentCls);
77731             me.fireEvent('scrollershow', me.horizontalScroller, 'horizontal');
77732         }
77733     },
77734
77735     
77736     hideVerticalScroller: function() {
77737         var me = this;
77738
77739         me.setHeaderReserveOffset(false);
77740         if (me.verticalScroller && me.verticalScroller.ownerCt === me) {
77741             me.removeDocked(me.verticalScroller, false);
77742             me.removeCls(me.verticalScrollerPresentCls);
77743             me.fireEvent('scrollerhide', me.verticalScroller, 'vertical');
77744         }
77745     },
77746
77747     
77748     showVerticalScroller: function() {
77749         var me = this;
77750
77751         me.setHeaderReserveOffset(true);
77752         if (me.verticalScroller && me.verticalScroller.ownerCt !== me) {
77753             me.addDocked(me.verticalScroller);
77754             me.addCls(me.verticalScrollerPresentCls);
77755             me.fireEvent('scrollershow', me.verticalScroller, 'vertical');
77756         }
77757     },
77758
77759     setHeaderReserveOffset: function (reserveOffset) {
77760         var headerCt = this.headerCt,
77761             layout = headerCt.layout;
77762
77763         
77764         if (layout && layout.reserveOffset !== reserveOffset) {
77765             layout.reserveOffset = reserveOffset;
77766             if (!this.suspendLayout) {
77767                 headerCt.doLayout();
77768             }
77769         }
77770     },
77771
77772     
77773     invalidateScroller: function() {
77774         var me = this,
77775             vScroll = me.verticalScroller,
77776             hScroll = me.horizontalScroller;
77777
77778         if (vScroll) {
77779             vScroll.invalidate();
77780         }
77781         if (hScroll) {
77782             hScroll.invalidate();
77783         }
77784     },
77785
77786     
77787     onHeaderMove: function(headerCt, header, fromIdx, toIdx) {
77788         this.view.refresh();
77789     },
77790
77791     
77792     onHeaderHide: function(headerCt, header) {
77793         this.invalidateScroller();
77794     },
77795
77796     onHeaderShow: function(headerCt, header) {
77797         this.invalidateScroller();
77798     },
77799
77800     getVerticalScroller: function() {
77801         return this.getScrollerOwner().down('gridscroller[dock=' + this.verticalScrollDock + ']');
77802     },
77803
77804     getHorizontalScroller: function() {
77805         return this.getScrollerOwner().down('gridscroller[dock=bottom]');
77806     },
77807
77808     onMouseWheel: function(e) {
77809         var me = this,
77810             vertScroller = me.getVerticalScroller(),
77811             horizScroller = me.getHorizontalScroller(),
77812             scrollDelta = -me.scrollDelta,
77813             deltas = e.getWheelDeltas(),
77814             deltaX = scrollDelta * deltas.x,
77815             deltaY = scrollDelta * deltas.y,
77816             vertScrollerEl, horizScrollerEl,
77817             vertScrollerElDom, horizScrollerElDom,
77818             horizontalCanScrollLeft, horizontalCanScrollRight,
77819             verticalCanScrollDown, verticalCanScrollUp;
77820
77821         
77822         if (horizScroller) {
77823             horizScrollerEl = horizScroller.scrollEl;
77824             if (horizScrollerEl) {
77825                 horizScrollerElDom = horizScrollerEl.dom;
77826                 horizontalCanScrollRight = horizScrollerElDom.scrollLeft !== horizScrollerElDom.scrollWidth - horizScrollerElDom.clientWidth;
77827                 horizontalCanScrollLeft  = horizScrollerElDom.scrollLeft !== 0;
77828             }
77829         }
77830         if (vertScroller) {
77831             vertScrollerEl = vertScroller.scrollEl;
77832             if (vertScrollerEl) {
77833                 vertScrollerElDom = vertScrollerEl.dom;
77834                 verticalCanScrollDown = vertScrollerElDom.scrollTop !== vertScrollerElDom.scrollHeight - vertScrollerElDom.clientHeight;
77835                 verticalCanScrollUp   = vertScrollerElDom.scrollTop !== 0;
77836             }
77837         }
77838
77839         if (horizScroller) {
77840             if ((deltaX < 0 && horizontalCanScrollLeft) || (deltaX > 0 && horizontalCanScrollRight)) {
77841                 e.stopEvent();
77842                 horizScroller.scrollByDeltaX(deltaX);
77843             }
77844         }
77845         if (vertScroller) {
77846             if ((deltaY < 0 && verticalCanScrollUp) || (deltaY > 0 && verticalCanScrollDown)) {
77847                 e.stopEvent();
77848                 vertScroller.scrollByDeltaY(deltaY);
77849             }
77850         }
77851     },
77852
77853     
77854     onViewReady: function() {
77855         var me = this;
77856         me.fireEvent('viewready', me);
77857         if (me.deferRowRender) {
77858             me.determineScrollbars();
77859             me.invalidateScroller();
77860         }
77861     },
77862
77863     
77864     onViewRefresh: function() {
77865         var me = this;
77866
77867         
77868         if (!me.rendering) {
77869             this.determineScrollbars();
77870             if (this.invalidateScrollerOnRefresh) {
77871                 this.invalidateScroller();
77872             }
77873         }
77874     },
77875
77876     
77877     setScrollTop: function(top) {
77878         var me               = this,
77879             rootCmp          = me.getScrollerOwner(),
77880             verticalScroller = me.getVerticalScroller();
77881
77882         rootCmp.virtualScrollTop = top;
77883         if (verticalScroller) {
77884             verticalScroller.setScrollTop(top);
77885         }
77886     },
77887
77888     getScrollerOwner: function() {
77889         var rootCmp = this;
77890         if (!this.scrollerOwner) {
77891             rootCmp = this.up('[scrollerOwner]');
77892         }
77893         return rootCmp;
77894     },
77895
77896     
77897     scrollByDeltaY: function(deltaY) {
77898         var verticalScroller = this.getVerticalScroller();
77899
77900         if (verticalScroller) {
77901             verticalScroller.scrollByDeltaY(deltaY);
77902         }
77903     },
77904
77905     
77906     scrollByDeltaX: function(deltaX) {
77907         var horizontalScroller = this.getHorizontalScroller();
77908
77909         if (horizontalScroller) {
77910             horizontalScroller.scrollByDeltaX(deltaX);
77911         }
77912     },
77913
77914     
77915     getLhsMarker: function() {
77916         var me = this;
77917
77918         if (!me.lhsMarker) {
77919             me.lhsMarker = Ext.DomHelper.append(me.el, {
77920                 cls: Ext.baseCSSPrefix + 'grid-resize-marker'
77921             }, true);
77922         }
77923         return me.lhsMarker;
77924     },
77925
77926     
77927     getRhsMarker: function() {
77928         var me = this;
77929
77930         if (!me.rhsMarker) {
77931             me.rhsMarker = Ext.DomHelper.append(me.el, {
77932                 cls: Ext.baseCSSPrefix + 'grid-resize-marker'
77933             }, true);
77934         }
77935         return me.rhsMarker;
77936     },
77937
77938     
77939     getSelectionModel: function(){
77940         if (!this.selModel) {
77941             this.selModel = {};
77942         }
77943
77944         var mode = 'SINGLE',
77945             type;
77946         if (this.simpleSelect) {
77947             mode = 'SIMPLE';
77948         } else if (this.multiSelect) {
77949             mode = 'MULTI';
77950         }
77951
77952         Ext.applyIf(this.selModel, {
77953             allowDeselect: this.allowDeselect,
77954             mode: mode
77955         });
77956
77957         if (!this.selModel.events) {
77958             type = this.selModel.selType || this.selType;
77959             this.selModel = Ext.create('selection.' + type, this.selModel);
77960         }
77961
77962         if (!this.selModel.hasRelaySetup) {
77963             this.relayEvents(this.selModel, [
77964                 'selectionchange', 'beforeselect', 'beforedeselect', 'select', 'deselect'
77965             ]);
77966             this.selModel.hasRelaySetup = true;
77967         }
77968
77969         
77970         
77971         if (this.disableSelection) {
77972             this.selModel.locked = true;
77973         }
77974         return this.selModel;
77975     },
77976
77977     onVerticalScroll: function(event, target) {
77978         var owner = this.getScrollerOwner(),
77979             items = owner.query('tableview'),
77980             i = 0,
77981             len = items.length;
77982
77983         for (; i < len; i++) {
77984             items[i].el.dom.scrollTop = target.scrollTop;
77985         }
77986     },
77987
77988     onHorizontalScroll: function(event, target) {
77989         var owner = this.getScrollerOwner(),
77990             items = owner.query('tableview'),
77991             center = items[1] || items[0];
77992
77993         center.el.dom.scrollLeft = target.scrollLeft;
77994         this.headerCt.el.dom.scrollLeft = target.scrollLeft;
77995     },
77996
77997     
77998     onStoreLoad: Ext.emptyFn,
77999
78000     getEditorParent: function() {
78001         return this.body;
78002     },
78003
78004     bindStore: function(store) {
78005         var me = this;
78006         me.store = store;
78007         me.getView().bindStore(store);
78008     },
78009     
78010     beforeDestroy: function(){
78011         
78012         
78013         
78014         Ext.destroy(this.horizontalScroller, this.verticalScroller);
78015         this.callParent();
78016     },
78017
78018     
78019     reconfigure: function(store, columns) {
78020         var me = this,
78021             headerCt = me.headerCt;
78022
78023         if (me.lockable) {
78024             me.reconfigureLockable(store, columns);
78025         } else {
78026             if (columns) {
78027                 headerCt.suspendLayout = true;
78028                 headerCt.removeAll();
78029                 headerCt.add(columns);
78030             }
78031             if (store) {
78032                 store = Ext.StoreManager.lookup(store);
78033                 me.bindStore(store);
78034             } else {
78035                 me.getView().refresh();
78036             }
78037             if (columns) {
78038                 headerCt.suspendLayout = false;
78039                 me.forceComponentLayout();
78040             }
78041         }
78042         me.fireEvent('reconfigure', me);
78043     }
78044 });
78045
78046 Ext.define('Ext.view.Table', {
78047     extend: 'Ext.view.View',
78048     alias: 'widget.tableview',
78049     uses: [
78050         'Ext.view.TableChunker',
78051         'Ext.util.DelayedTask',
78052         'Ext.util.MixedCollection'
78053     ],
78054
78055     baseCls: Ext.baseCSSPrefix + 'grid-view',
78056
78057     
78058     itemSelector: '.' + Ext.baseCSSPrefix + 'grid-row',
78059     
78060     cellSelector: '.' + Ext.baseCSSPrefix + 'grid-cell',
78061
78062     selectedItemCls: Ext.baseCSSPrefix + 'grid-row-selected',
78063     selectedCellCls: Ext.baseCSSPrefix + 'grid-cell-selected',
78064     focusedItemCls: Ext.baseCSSPrefix + 'grid-row-focused',
78065     overItemCls: Ext.baseCSSPrefix + 'grid-row-over',
78066     altRowCls:   Ext.baseCSSPrefix + 'grid-row-alt',
78067     rowClsRe: /(?:^|\s*)grid-row-(first|last|alt)(?:\s+|$)/g,
78068     cellRe: new RegExp('x-grid-cell-([^\\s]+) ', ''),
78069
78070     
78071     trackOver: true,
78072
78073     
78074     getRowClass: null,
78075
78076     initComponent: function() {
78077         var me = this;
78078
78079         me.scrollState = {};
78080         me.selModel.view = me;
78081         me.headerCt.view = me;
78082         me.initFeatures();
78083         me.tpl = '<div></div>';
78084         me.callParent();
78085         me.mon(me.store, {
78086             load: me.onStoreLoad,
78087             scope: me
78088         });
78089
78090         
78091         
78092         
78093         
78094         
78095         
78096         
78097         
78098         
78099     },
78100
78101     
78102     onStoreLoad: function(){
78103         var me = this;
78104
78105         if (me.invalidateScrollerOnRefresh) {
78106             if (Ext.isGecko) {
78107                 if (!me.scrollToTopTask) {
78108                     me.scrollToTopTask = Ext.create('Ext.util.DelayedTask', me.scrollToTop, me);
78109                 }
78110                 me.scrollToTopTask.delay(1);
78111             } else {
78112                 me    .scrollToTop();
78113             }
78114         }
78115     },
78116
78117     
78118     scrollToTop: Ext.emptyFn,
78119
78120     
78121     addElListener: function(eventName, fn, scope){
78122         this.mon(this, eventName, fn, scope, {
78123             element: 'el'
78124         });
78125     },
78126
78127     
78128     getGridColumns: function() {
78129         return this.headerCt.getGridColumns();
78130     },
78131
78132     
78133     getHeaderAtIndex: function(index) {
78134         return this.headerCt.getHeaderAtIndex(index);
78135     },
78136
78137     
78138     getCell: function(record, column) {
78139         var row = this.getNode(record);
78140         return Ext.fly(row).down(column.getCellSelector());
78141     },
78142
78143     
78144     getFeature: function(id) {
78145         var features = this.featuresMC;
78146         if (features) {
78147             return features.get(id);
78148         }
78149     },
78150
78151     
78152     initFeatures: function() {
78153         var me = this,
78154             i = 0,
78155             features,
78156             len;
78157
78158         me.features = me.features || [];
78159         features = me.features;
78160         len = features.length;
78161
78162         me.featuresMC = Ext.create('Ext.util.MixedCollection');
78163         for (; i < len; i++) {
78164             
78165             if (!features[i].isFeature) {
78166                 features[i] = Ext.create('feature.' + features[i].ftype, features[i]);
78167             }
78168             
78169             features[i].view = me;
78170             me.featuresMC.add(features[i]);
78171         }
78172     },
78173
78174     
78175     attachEventsForFeatures: function() {
78176         var features = this.features,
78177             ln       = features.length,
78178             i        = 0;
78179
78180         for (; i < ln; i++) {
78181             if (features[i].isFeature) {
78182                 features[i].attachEvents();
78183             }
78184         }
78185     },
78186
78187     afterRender: function() {
78188         var me = this;
78189
78190         me.callParent();
78191         me.mon(me.el, {
78192             scroll: me.fireBodyScroll,
78193             scope: me
78194         });
78195         me.el.unselectable();
78196         me.attachEventsForFeatures();
78197     },
78198
78199     fireBodyScroll: function(e, t) {
78200         this.fireEvent('bodyscroll', e, t);
78201     },
78202
78203     
78204     
78205     prepareData: function(data, idx, record) {
78206         var me       = this,
78207             orig     = me.headerCt.prepareData(data, idx, record, me, me.ownerCt),
78208             features = me.features,
78209             ln       = features.length,
78210             i        = 0,
78211             node, feature;
78212
78213         for (; i < ln; i++) {
78214             feature = features[i];
78215             if (feature.isFeature) {
78216                 Ext.apply(orig, feature.getAdditionalData(data, idx, record, orig, me));
78217             }
78218         }
78219
78220         return orig;
78221     },
78222
78223     
78224     collectData: function(records, startIndex) {
78225         var preppedRecords = this.callParent(arguments),
78226             headerCt  = this.headerCt,
78227             fullWidth = headerCt.getFullWidth(),
78228             features  = this.features,
78229             ln = features.length,
78230             o = {
78231                 rows: preppedRecords,
78232                 fullWidth: fullWidth
78233             },
78234             i  = 0,
78235             feature,
78236             j = 0,
78237             jln,
78238             rowParams;
78239
78240         jln = preppedRecords.length;
78241         
78242         
78243         if (this.getRowClass) {
78244             for (; j < jln; j++) {
78245                 rowParams = {};
78246                 preppedRecords[j]['rowCls'] = this.getRowClass(records[j], j, rowParams, this.store);
78247             }
78248         }
78249         
78250         
78251         for (; i < ln; i++) {
78252             feature = features[i];
78253             if (feature.isFeature && feature.collectData && !feature.disabled) {
78254                 o = feature.collectData(records, preppedRecords, startIndex, fullWidth, o);
78255                 break;
78256             }
78257         }
78258         return o;
78259     },
78260
78261     
78262     
78263     onHeaderResize: function(header, w, suppressFocus) {
78264         var me = this,
78265             el = me.el;
78266
78267         if (el) {
78268             me.saveScrollState();
78269             
78270             
78271             
78272
78273             
78274             
78275             
78276             if (Ext.isIE6 || Ext.isIE7) {
78277                 if (header.el.hasCls(Ext.baseCSSPrefix + 'column-header-first')) {
78278                     w += 1;
78279                 }
78280             }
78281             el.select('.' + Ext.baseCSSPrefix + 'grid-col-resizer-'+header.id).setWidth(w);
78282             el.select('.' + Ext.baseCSSPrefix + 'grid-table-resizer').setWidth(me.headerCt.getFullWidth());
78283             me.restoreScrollState();
78284             if (!me.ignoreTemplate) {
78285                 me.setNewTemplate();
78286             }
78287             if (!suppressFocus) {
78288                 me.el.focus();
78289             }
78290         }
78291     },
78292
78293     
78294     onHeaderShow: function(headerCt, header, suppressFocus) {
78295         var me = this;
78296         me.ignoreTemplate = true;
78297         
78298         if (header.oldWidth) {
78299             me.onHeaderResize(header, header.oldWidth, suppressFocus);
78300             delete header.oldWidth;
78301         
78302         
78303         
78304         } else if (header.width && !header.flex) {
78305             me.onHeaderResize(header, header.width, suppressFocus);
78306         }
78307         delete me.ignoreTemplate;
78308         me.setNewTemplate();
78309     },
78310
78311     
78312     onHeaderHide: function(headerCt, header, suppressFocus) {
78313         this.onHeaderResize(header, 0, suppressFocus);
78314     },
78315
78316     
78317     setNewTemplate: function() {
78318         var me = this,
78319             columns = me.headerCt.getColumnsForTpl(true);
78320
78321         me.tpl = me.getTableChunker().getTableTpl({
78322             columns: columns,
78323             features: me.features
78324         });
78325     },
78326
78327     
78328     getTableChunker: function() {
78329         return this.chunker || Ext.view.TableChunker;
78330     },
78331
78332     
78333     addRowCls: function(rowInfo, cls) {
78334         var row = this.getNode(rowInfo);
78335         if (row) {
78336             Ext.fly(row).addCls(cls);
78337         }
78338     },
78339
78340     
78341     removeRowCls: function(rowInfo, cls) {
78342         var row = this.getNode(rowInfo);
78343         if (row) {
78344             Ext.fly(row).removeCls(cls);
78345         }
78346     },
78347
78348     
78349     onRowSelect : function(rowIdx) {
78350         this.addRowCls(rowIdx, this.selectedItemCls);
78351     },
78352
78353     
78354     onRowDeselect : function(rowIdx) {
78355         var me = this;
78356
78357         me.removeRowCls(rowIdx, me.selectedItemCls);
78358         me.removeRowCls(rowIdx, me.focusedItemCls);
78359     },
78360
78361     onCellSelect: function(position) {
78362         var cell = this.getCellByPosition(position);
78363         if (cell) {
78364             cell.addCls(this.selectedCellCls);
78365         }
78366     },
78367
78368     onCellDeselect: function(position) {
78369         var cell = this.getCellByPosition(position);
78370         if (cell) {
78371             cell.removeCls(this.selectedCellCls);
78372         }
78373
78374     },
78375
78376     onCellFocus: function(position) {
78377         
78378         this.focusCell(position);
78379     },
78380
78381     getCellByPosition: function(position) {
78382         var row    = position.row,
78383             column = position.column,
78384             store  = this.store,
78385             node   = this.getNode(row),
78386             header = this.headerCt.getHeaderAtIndex(column),
78387             cellSelector,
78388             cell = false;
78389
78390         if (header && node) {
78391             cellSelector = header.getCellSelector();
78392             cell = Ext.fly(node).down(cellSelector);
78393         }
78394         return cell;
78395     },
78396
78397     
78398     
78399     onRowFocus: function(rowIdx, highlight, supressFocus) {
78400         var me = this,
78401             row = me.getNode(rowIdx);
78402
78403         if (highlight) {
78404             me.addRowCls(rowIdx, me.focusedItemCls);
78405             if (!supressFocus) {
78406                 me.focusRow(rowIdx);
78407             }
78408             
78409         } else {
78410             me.removeRowCls(rowIdx, me.focusedItemCls);
78411         }
78412     },
78413
78414     
78415     focusRow: function(rowIdx) {
78416         var me         = this,
78417             row        = me.getNode(rowIdx),
78418             el         = me.el,
78419             adjustment = 0,
78420             panel      = me.ownerCt,
78421             rowRegion,
78422             elRegion,
78423             record;
78424
78425         if (row && el) {
78426             elRegion  = el.getRegion();
78427             rowRegion = Ext.fly(row).getRegion();
78428             
78429             if (rowRegion.top < elRegion.top) {
78430                 adjustment = rowRegion.top - elRegion.top;
78431             
78432             } else if (rowRegion.bottom > elRegion.bottom) {
78433                 adjustment = rowRegion.bottom - elRegion.bottom;
78434             }
78435             record = me.getRecord(row);
78436             rowIdx = me.store.indexOf(record);
78437
78438             if (adjustment) {
78439                 
78440                 panel.scrollByDeltaY(adjustment);
78441             }
78442             me.fireEvent('rowfocus', record, row, rowIdx);
78443         }
78444     },
78445
78446     focusCell: function(position) {
78447         var me          = this,
78448             cell        = me.getCellByPosition(position),
78449             el          = me.el,
78450             adjustmentY = 0,
78451             adjustmentX = 0,
78452             elRegion    = el.getRegion(),
78453             panel       = me.ownerCt,
78454             cellRegion,
78455             record;
78456
78457         if (cell) {
78458             cellRegion = cell.getRegion();
78459             
78460             if (cellRegion.top < elRegion.top) {
78461                 adjustmentY = cellRegion.top - elRegion.top;
78462             
78463             } else if (cellRegion.bottom > elRegion.bottom) {
78464                 adjustmentY = cellRegion.bottom - elRegion.bottom;
78465             }
78466
78467             
78468             if (cellRegion.left < elRegion.left) {
78469                 adjustmentX = cellRegion.left - elRegion.left;
78470             
78471             } else if (cellRegion.right > elRegion.right) {
78472                 adjustmentX = cellRegion.right - elRegion.right;
78473             }
78474
78475             if (adjustmentY) {
78476                 
78477                 panel.scrollByDeltaY(adjustmentY);
78478             }
78479             if (adjustmentX) {
78480                 panel.scrollByDeltaX(adjustmentX);
78481             }
78482             el.focus();
78483             me.fireEvent('cellfocus', record, cell, position);
78484         }
78485     },
78486
78487     
78488     scrollByDelta: function(delta, dir) {
78489         dir = dir || 'scrollTop';
78490         var elDom = this.el.dom;
78491         elDom[dir] = (elDom[dir] += delta);
78492     },
78493
78494     onUpdate: function(ds, index) {
78495         this.callParent(arguments);
78496     },
78497
78498     
78499     saveScrollState: function() {
78500         if (this.rendered) {
78501             var dom = this.el.dom, 
78502                 state = this.scrollState;
78503             
78504             state.left = dom.scrollLeft;
78505             state.top = dom.scrollTop;
78506         }
78507     },
78508
78509     
78510     restoreScrollState: function() {
78511         if (this.rendered) {
78512             var dom = this.el.dom, 
78513                 state = this.scrollState, 
78514                 headerEl = this.headerCt.el.dom;
78515             
78516             headerEl.scrollLeft = dom.scrollLeft = state.left;
78517             dom.scrollTop = state.top;
78518         }
78519     },
78520
78521     
78522     refresh: function() {
78523         this.setNewTemplate();
78524         this.callParent(arguments);
78525     },
78526
78527     processItemEvent: function(record, row, rowIndex, e) {
78528         var me = this,
78529             cell = e.getTarget(me.cellSelector, row),
78530             cellIndex = cell ? cell.cellIndex : -1,
78531             map = me.statics().EventMap,
78532             selModel = me.getSelectionModel(),
78533             type = e.type,
78534             result;
78535
78536         if (type == 'keydown' && !cell && selModel.getCurrentPosition) {
78537             
78538             cell = me.getCellByPosition(selModel.getCurrentPosition());
78539             if (cell) {
78540                 cell = cell.dom;
78541                 cellIndex = cell.cellIndex;
78542             }
78543         }
78544
78545         result = me.fireEvent('uievent', type, me, cell, rowIndex, cellIndex, e);
78546
78547         if (result === false || me.callParent(arguments) === false) {
78548             return false;
78549         }
78550
78551         
78552         if (type == 'mouseover' || type == 'mouseout') {
78553             return true;
78554         }
78555
78556         return !(
78557             
78558             (me['onBeforeCell' + map[type]](cell, cellIndex, record, row, rowIndex, e) === false) ||
78559             (me.fireEvent('beforecell' + type, me, cell, cellIndex, record, row, rowIndex, e) === false) ||
78560             (me['onCell' + map[type]](cell, cellIndex, record, row, rowIndex, e) === false) ||
78561             (me.fireEvent('cell' + type, me, cell, cellIndex, record, row, rowIndex, e) === false)
78562         );
78563     },
78564
78565     processSpecialEvent: function(e) {
78566         var me = this,
78567             map = me.statics().EventMap,
78568             features = me.features,
78569             ln = features.length,
78570             type = e.type,
78571             i, feature, prefix, featureTarget,
78572             beforeArgs, args,
78573             panel = me.ownerCt;
78574
78575         me.callParent(arguments);
78576
78577         if (type == 'mouseover' || type == 'mouseout') {
78578             return;
78579         }
78580
78581         for (i = 0; i < ln; i++) {
78582             feature = features[i];
78583             if (feature.hasFeatureEvent) {
78584                 featureTarget = e.getTarget(feature.eventSelector, me.getTargetEl());
78585                 if (featureTarget) {
78586                     prefix = feature.eventPrefix;
78587                     
78588                     
78589                     beforeArgs = feature.getFireEventArgs('before' + prefix + type, me, featureTarget, e);
78590                     args = feature.getFireEventArgs(prefix + type, me, featureTarget, e);
78591
78592                     if (
78593                         
78594                         (me.fireEvent.apply(me, beforeArgs) === false) ||
78595                         
78596                         (panel.fireEvent.apply(panel, beforeArgs) === false) ||
78597                         
78598                         (me.fireEvent.apply(me, args) === false) ||
78599                         
78600                         (panel.fireEvent.apply(panel, args) === false)
78601                     ) {
78602                         return false;
78603                     }
78604                 }
78605             }
78606         }
78607         return true;
78608     },
78609
78610     onCellMouseDown: Ext.emptyFn,
78611     onCellMouseUp: Ext.emptyFn,
78612     onCellClick: Ext.emptyFn,
78613     onCellDblClick: Ext.emptyFn,
78614     onCellContextMenu: Ext.emptyFn,
78615     onCellKeyDown: Ext.emptyFn,
78616     onBeforeCellMouseDown: Ext.emptyFn,
78617     onBeforeCellMouseUp: Ext.emptyFn,
78618     onBeforeCellClick: Ext.emptyFn,
78619     onBeforeCellDblClick: Ext.emptyFn,
78620     onBeforeCellContextMenu: Ext.emptyFn,
78621     onBeforeCellKeyDown: Ext.emptyFn,
78622
78623     
78624     expandToFit: function(header) {
78625         if (header) {
78626             var maxWidth = this.getMaxContentWidth(header);
78627             delete header.flex;
78628             header.setWidth(maxWidth);
78629         }
78630     },
78631
78632     
78633     getMaxContentWidth: function(header) {
78634         var cellSelector = header.getCellInnerSelector(),
78635             cells        = this.el.query(cellSelector),
78636             i = 0,
78637             ln = cells.length,
78638             maxWidth = header.el.dom.scrollWidth,
78639             scrollWidth;
78640
78641         for (; i < ln; i++) {
78642             scrollWidth = cells[i].scrollWidth;
78643             if (scrollWidth > maxWidth) {
78644                 maxWidth = scrollWidth;
78645             }
78646         }
78647         return maxWidth;
78648     },
78649
78650     getPositionByEvent: function(e) {
78651         var me       = this,
78652             cellNode = e.getTarget(me.cellSelector),
78653             rowNode  = e.getTarget(me.itemSelector),
78654             record   = me.getRecord(rowNode),
78655             header   = me.getHeaderByCell(cellNode);
78656
78657         return me.getPosition(record, header);
78658     },
78659
78660     getHeaderByCell: function(cell) {
78661         if (cell) {
78662             var m = cell.className.match(this.cellRe);
78663             if (m && m[1]) {
78664                 return Ext.getCmp(m[1]);
78665             }
78666         }
78667         return false;
78668     },
78669
78670     
78671     walkCells: function(pos, direction, e, preventWrap, verifierFn, scope) {
78672         var me       = this,
78673             row      = pos.row,
78674             column   = pos.column,
78675             rowCount = me.store.getCount(),
78676             firstCol = me.getFirstVisibleColumnIndex(),
78677             lastCol  = me.getLastVisibleColumnIndex(),
78678             newPos   = {row: row, column: column},
78679             activeHeader = me.headerCt.getHeaderAtIndex(column);
78680
78681         
78682         if (!activeHeader || activeHeader.hidden) {
78683             return false;
78684         }
78685
78686         e = e || {};
78687         direction = direction.toLowerCase();
78688         switch (direction) {
78689             case 'right':
78690                 
78691                 if (column === lastCol) {
78692                     
78693                     if (preventWrap || row === rowCount - 1) {
78694                         return false;
78695                     }
78696                     if (!e.ctrlKey) {
78697                         
78698                         newPos.row = row + 1;
78699                         newPos.column = firstCol;
78700                     }
78701                 
78702                 } else {
78703                     if (!e.ctrlKey) {
78704                         newPos.column = column + me.getRightGap(activeHeader);
78705                     } else {
78706                         newPos.column = lastCol;
78707                     }
78708                 }
78709                 break;
78710
78711             case 'left':
78712                 
78713                 if (column === firstCol) {
78714                     
78715                     if (preventWrap || row === 0) {
78716                         return false;
78717                     }
78718                     if (!e.ctrlKey) {
78719                         
78720                         newPos.row = row - 1;
78721                         newPos.column = lastCol;
78722                     }
78723                 
78724                 } else {
78725                     if (!e.ctrlKey) {
78726                         newPos.column = column + me.getLeftGap(activeHeader);
78727                     } else {
78728                         newPos.column = firstCol;
78729                     }
78730                 }
78731                 break;
78732
78733             case 'up':
78734                 
78735                 if (row === 0) {
78736                     return false;
78737                 
78738                 } else {
78739                     if (!e.ctrlKey) {
78740                         newPos.row = row - 1;
78741                     } else {
78742                         newPos.row = 0;
78743                     }
78744                 }
78745                 break;
78746
78747             case 'down':
78748                 
78749                 if (row === rowCount - 1) {
78750                     return false;
78751                 
78752                 } else {
78753                     if (!e.ctrlKey) {
78754                         newPos.row = row + 1;
78755                     } else {
78756                         newPos.row = rowCount - 1;
78757                     }
78758                 }
78759                 break;
78760         }
78761
78762         if (verifierFn && verifierFn.call(scope || window, newPos) !== true) {
78763             return false;
78764         } else {
78765             return newPos;
78766         }
78767     },
78768     getFirstVisibleColumnIndex: function() {
78769         var headerCt   = this.getHeaderCt(),
78770             allColumns = headerCt.getGridColumns(),
78771             visHeaders = Ext.ComponentQuery.query(':not([hidden])', allColumns),
78772             firstHeader = visHeaders[0];
78773
78774         return headerCt.getHeaderIndex(firstHeader);
78775     },
78776
78777     getLastVisibleColumnIndex: function() {
78778         var headerCt   = this.getHeaderCt(),
78779             allColumns = headerCt.getGridColumns(),
78780             visHeaders = Ext.ComponentQuery.query(':not([hidden])', allColumns),
78781             lastHeader = visHeaders[visHeaders.length - 1];
78782
78783         return headerCt.getHeaderIndex(lastHeader);
78784     },
78785
78786     getHeaderCt: function() {
78787         return this.headerCt;
78788     },
78789
78790     getPosition: function(record, header) {
78791         var me = this,
78792             store = me.store,
78793             gridCols = me.headerCt.getGridColumns();
78794
78795         return {
78796             row: store.indexOf(record),
78797             column: Ext.Array.indexOf(gridCols, header)
78798         };
78799     },
78800
78801     
78802     getRightGap: function(activeHeader) {
78803         var headerCt        = this.getHeaderCt(),
78804             headers         = headerCt.getGridColumns(),
78805             activeHeaderIdx = Ext.Array.indexOf(headers, activeHeader),
78806             i               = activeHeaderIdx + 1,
78807             nextIdx;
78808
78809         for (; i <= headers.length; i++) {
78810             if (!headers[i].hidden) {
78811                 nextIdx = i;
78812                 break;
78813             }
78814         }
78815
78816         return nextIdx - activeHeaderIdx;
78817     },
78818
78819     beforeDestroy: function() {
78820         if (this.rendered) {
78821             this.el.removeAllListeners();
78822         }
78823         this.callParent(arguments);
78824     },
78825
78826     
78827     getLeftGap: function(activeHeader) {
78828         var headerCt        = this.getHeaderCt(),
78829             headers         = headerCt.getGridColumns(),
78830             activeHeaderIdx = Ext.Array.indexOf(headers, activeHeader),
78831             i               = activeHeaderIdx - 1,
78832             prevIdx;
78833
78834         for (; i >= 0; i--) {
78835             if (!headers[i].hidden) {
78836                 prevIdx = i;
78837                 break;
78838             }
78839         }
78840
78841         return prevIdx - activeHeaderIdx;
78842     }
78843 });
78844
78845 Ext.define('Ext.grid.View', {
78846     extend: 'Ext.view.Table',
78847     alias: 'widget.gridview',
78848
78849     
78850     stripeRows: true,
78851
78852     invalidateScrollerOnRefresh: true,
78853
78854     
78855     scrollToTop : function(){
78856         if (this.rendered) {
78857             var section = this.ownerCt,
78858                 verticalScroller = section.verticalScroller;
78859
78860             if (verticalScroller) {
78861                 verticalScroller.scrollToTop();
78862             }
78863         }
78864     },
78865
78866     
78867     onAdd: function(ds, records, index) {
78868         this.callParent(arguments);
78869         this.doStripeRows(index);
78870     },
78871
78872     
78873     onRemove: function(ds, records, index) {
78874         this.callParent(arguments);
78875         this.doStripeRows(index);
78876     },
78877
78878     onUpdate: function(ds, record, operation) {
78879         var index = ds.indexOf(record);
78880         this.callParent(arguments);
78881         this.doStripeRows(index, index);
78882     },
78883
78884     
78885     doStripeRows: function(startRow, endRow) {
78886         
78887         if (this.stripeRows) {
78888             var rows   = this.getNodes(startRow, endRow),
78889                 rowsLn = rows.length,
78890                 i      = 0,
78891                 row;
78892
78893             for (; i < rowsLn; i++) {
78894                 row = rows[i];
78895                 
78896                 row.className = row.className.replace(this.rowClsRe, ' ');
78897                 startRow++;
78898                 
78899                 if (startRow % 2 === 0) {
78900                     row.className += (' ' + this.altRowCls);
78901                 }
78902             }
78903         }
78904     },
78905
78906     refresh: function(firstPass) {
78907         this.callParent(arguments);
78908         this.doStripeRows(0);
78909         
78910         var g = this.up('gridpanel');
78911         if (g && this.invalidateScrollerOnRefresh) {
78912             g.invalidateScroller();
78913         }
78914     }
78915 });
78916
78917
78918 Ext.define('Ext.grid.Panel', {
78919     extend: 'Ext.panel.Table',
78920     requires: ['Ext.grid.View'],
78921     alias: ['widget.gridpanel', 'widget.grid'],
78922     alternateClassName: ['Ext.list.ListView', 'Ext.ListView', 'Ext.grid.GridPanel'],
78923     viewType: 'gridview',
78924
78925     lockable: false,
78926
78927     
78928     
78929     normalCfgCopy: ['invalidateScrollerOnRefresh', 'verticalScroller', 'verticalScrollDock', 'verticalScrollerType', 'scroll'],
78930     lockedCfgCopy: ['invalidateScrollerOnRefresh'],
78931
78932     
78933
78934     initComponent: function() {
78935         var me = this;
78936
78937         if (me.columnLines) {
78938             me.setColumnLines(me.columnLines);
78939         }
78940
78941         me.callParent();
78942     },
78943
78944     setColumnLines: function(show) {
78945         var me = this,
78946             method = (show) ? 'addClsWithUI' : 'removeClsWithUI';
78947
78948         me[method]('with-col-lines');
78949     }
78950 });
78951
78952
78953
78954
78955
78956
78957
78958
78959
78960
78961 Ext.define('Ext.grid.RowEditor', {
78962     extend: 'Ext.form.Panel',
78963     requires: [
78964         'Ext.tip.ToolTip',
78965         'Ext.util.HashMap',
78966         'Ext.util.KeyNav'
78967     ],
78968
78969     saveBtnText  : 'Update',
78970     cancelBtnText: 'Cancel',
78971     errorsText: 'Errors',
78972     dirtyText: 'You need to commit or cancel your changes',
78973
78974     lastScrollLeft: 0,
78975     lastScrollTop: 0,
78976
78977     border: false,
78978     
78979     
78980     
78981     hideMode: 'offsets',
78982
78983     initComponent: function() {
78984         var me = this,
78985             form;
78986
78987         me.cls = Ext.baseCSSPrefix + 'grid-row-editor';
78988
78989         me.layout = {
78990             type: 'hbox',
78991             align: 'middle'
78992         };
78993
78994         
78995         
78996         me.columns = Ext.create('Ext.util.HashMap');
78997         me.columns.getKey = function(columnHeader) {
78998             var f;
78999             if (columnHeader.getEditor) {
79000                 f = columnHeader.getEditor();
79001                 if (f) {
79002                     return f.id;
79003                 }
79004             }
79005             return columnHeader.id;
79006         };
79007         me.mon(me.columns, {
79008             add: me.onFieldAdd,
79009             remove: me.onFieldRemove,
79010             replace: me.onFieldReplace,
79011             scope: me
79012         });
79013
79014         me.callParent(arguments);
79015
79016         if (me.fields) {
79017             me.setField(me.fields);
79018             delete me.fields;
79019         }
79020
79021         form = me.getForm();
79022         form.trackResetOnLoad = true;
79023     },
79024
79025     onFieldChange: function() {
79026         var me = this,
79027             form = me.getForm(),
79028             valid = form.isValid();
79029         if (me.errorSummary && me.isVisible()) {
79030             me[valid ? 'hideToolTip' : 'showToolTip']();
79031         }
79032         if (me.floatingButtons) {
79033             me.floatingButtons.child('#update').setDisabled(!valid);
79034         }
79035         me.isValid = valid;
79036     },
79037
79038     afterRender: function() {
79039         var me = this,
79040             plugin = me.editingPlugin;
79041
79042         me.callParent(arguments);
79043         me.mon(me.renderTo, 'scroll', me.onCtScroll, me, { buffer: 100 });
79044
79045         
79046         me.mon(me.el, {
79047             click: Ext.emptyFn,
79048             stopPropagation: true
79049         });
79050
79051         me.el.swallowEvent([
79052             'keypress',
79053             'keydown'
79054         ]);
79055
79056         me.keyNav = Ext.create('Ext.util.KeyNav', me.el, {
79057             enter: plugin.completeEdit,
79058             esc: plugin.onEscKey,
79059             scope: plugin
79060         });
79061
79062         me.mon(plugin.view, {
79063             beforerefresh: me.onBeforeViewRefresh,
79064             refresh: me.onViewRefresh,
79065             scope: me
79066         });
79067     },
79068
79069     onBeforeViewRefresh: function(view) {
79070         var me = this,
79071             viewDom = view.el.dom;
79072
79073         if (me.el.dom.parentNode === viewDom) {
79074             viewDom.removeChild(me.el.dom);
79075         }
79076     },
79077
79078     onViewRefresh: function(view) {
79079         var me = this,
79080             viewDom = view.el.dom,
79081             context = me.context,
79082             idx;
79083
79084         viewDom.appendChild(me.el.dom);
79085
79086         
79087         if (context && (idx = context.store.indexOf(context.record)) >= 0) {
79088             context.row = view.getNode(idx);
79089             me.reposition();
79090             if (me.tooltip && me.tooltip.isVisible()) {
79091                 me.tooltip.setTarget(context.row);
79092             }
79093         } else {
79094             me.editingPlugin.cancelEdit();
79095         }
79096     },
79097
79098     onCtScroll: function(e, target) {
79099         var me = this,
79100             scrollTop  = target.scrollTop,
79101             scrollLeft = target.scrollLeft;
79102
79103         if (scrollTop !== me.lastScrollTop) {
79104             me.lastScrollTop = scrollTop;
79105             if ((me.tooltip && me.tooltip.isVisible()) || me.hiddenTip) {
79106                 me.repositionTip();
79107             }
79108         }
79109         if (scrollLeft !== me.lastScrollLeft) {
79110             me.lastScrollLeft = scrollLeft;
79111             me.reposition();
79112         }
79113     },
79114
79115     onColumnAdd: function(column) {
79116         this.setField(column);
79117     },
79118
79119     onColumnRemove: function(column) {
79120         this.columns.remove(column);
79121     },
79122
79123     onColumnResize: function(column, width) {
79124         column.getEditor().setWidth(width - 2);
79125         if (this.isVisible()) {
79126             this.reposition();
79127         }
79128     },
79129
79130     onColumnHide: function(column) {
79131         column.getEditor().hide();
79132         if (this.isVisible()) {
79133             this.reposition();
79134         }
79135     },
79136
79137     onColumnShow: function(column) {
79138         var field = column.getEditor();
79139         field.setWidth(column.getWidth() - 2).show();
79140         if (this.isVisible()) {
79141             this.reposition();
79142         }
79143     },
79144
79145     onColumnMove: function(column, fromIdx, toIdx) {
79146         var field = column.getEditor();
79147         if (this.items.indexOf(field) != toIdx) {
79148             this.move(fromIdx, toIdx);
79149         }
79150     },
79151
79152     onFieldAdd: function(map, fieldId, column) {
79153         var me = this,
79154             colIdx = me.editingPlugin.grid.headerCt.getHeaderIndex(column),
79155             field = column.getEditor({ xtype: 'displayfield' });
79156
79157         me.insert(colIdx, field);
79158     },
79159
79160     onFieldRemove: function(map, fieldId, column) {
79161         var me = this,
79162             field = column.getEditor(),
79163             fieldEl = field.el;
79164         me.remove(field, false);
79165         if (fieldEl) {
79166             fieldEl.remove();
79167         }
79168     },
79169
79170     onFieldReplace: function(map, fieldId, column, oldColumn) {
79171         var me = this;
79172         me.onFieldRemove(map, fieldId, oldColumn);
79173     },
79174
79175     clearFields: function() {
79176         var me = this,
79177             map = me.columns;
79178         map.each(function(fieldId) {
79179             map.removeAtKey(fieldId);
79180         });
79181     },
79182
79183     getFloatingButtons: function() {
79184         var me = this,
79185             cssPrefix = Ext.baseCSSPrefix,
79186             btnsCss = cssPrefix + 'grid-row-editor-buttons',
79187             plugin = me.editingPlugin,
79188             btns;
79189
79190         if (!me.floatingButtons) {
79191             btns = me.floatingButtons = Ext.create('Ext.Container', {
79192                 renderTpl: [
79193                     '<div class="{baseCls}-ml"></div>',
79194                     '<div class="{baseCls}-mr"></div>',
79195                     '<div class="{baseCls}-bl"></div>',
79196                     '<div class="{baseCls}-br"></div>',
79197                     '<div class="{baseCls}-bc"></div>'
79198                 ],
79199
79200                 renderTo: me.el,
79201                 baseCls: btnsCss,
79202                 layout: {
79203                     type: 'hbox',
79204                     align: 'middle'
79205                 },
79206                 defaults: {
79207                     margins: '0 1 0 1'
79208                 },
79209                 items: [{
79210                     itemId: 'update',
79211                     flex: 1,
79212                     xtype: 'button',
79213                     handler: plugin.completeEdit,
79214                     scope: plugin,
79215                     text: me.saveBtnText,
79216                     disabled: !me.isValid
79217                 }, {
79218                     flex: 1,
79219                     xtype: 'button',
79220                     handler: plugin.cancelEdit,
79221                     scope: plugin,
79222                     text: me.cancelBtnText
79223                 }]
79224             });
79225
79226             
79227             me.mon(btns.el, {
79228                 
79229                 
79230                 mousedown: Ext.emptyFn,
79231                 click: Ext.emptyFn,
79232                 stopEvent: true
79233             });
79234         }
79235         return me.floatingButtons;
79236     },
79237
79238     reposition: function(animateConfig) {
79239         var me = this,
79240             context = me.context,
79241             row = context && Ext.get(context.row),
79242             btns = me.getFloatingButtons(),
79243             btnEl = btns.el,
79244             grid = me.editingPlugin.grid,
79245             viewEl = grid.view.el,
79246             scroller = grid.verticalScroller,
79247
79248             
79249             
79250             mainBodyWidth = grid.headerCt.getFullWidth(),
79251             scrollerWidth = grid.getWidth(),
79252
79253             
79254             
79255             width = Math.min(mainBodyWidth, scrollerWidth),
79256             scrollLeft = grid.view.el.dom.scrollLeft,
79257             btnWidth = btns.getWidth(),
79258             left = (width - btnWidth) / 2 + scrollLeft,
79259             y, rowH, newHeight,
79260
79261             invalidateScroller = function() {
79262                 if (scroller) {
79263                     scroller.invalidate();
79264                     btnEl.scrollIntoView(viewEl, false);
79265                 }
79266                 if (animateConfig && animateConfig.callback) {
79267                     animateConfig.callback.call(animateConfig.scope || me);
79268                 }
79269             };
79270
79271         
79272         if (row && Ext.isElement(row.dom)) {
79273             
79274             
79275             row.scrollIntoView(viewEl, false);
79276
79277             
79278             
79279             
79280             y = row.getXY()[1] - 5;
79281             rowH = row.getHeight();
79282             newHeight = rowH + 10;
79283
79284             
79285             
79286             
79287             
79288             if (Ext.isIE) {
79289                 newHeight += 2;
79290             }
79291
79292             
79293             if (me.getHeight() != newHeight) {
79294                 me.setHeight(newHeight);
79295                 me.el.setLeft(0);
79296             }
79297
79298             if (animateConfig) {
79299                 var animObj = {
79300                     to: {
79301                         y: y
79302                     },
79303                     duration: animateConfig.duration || 125,
79304                     listeners: {
79305                         afteranimate: function() {
79306                             invalidateScroller();
79307                             y = row.getXY()[1] - 5;
79308                             me.el.setY(y);
79309                         }
79310                     }
79311                 };
79312                 me.animate(animObj);
79313             } else {
79314                 me.el.setY(y);
79315                 invalidateScroller();
79316             }
79317         }
79318         if (me.getWidth() != mainBodyWidth) {
79319             me.setWidth(mainBodyWidth);
79320         }
79321         btnEl.setLeft(left);
79322     },
79323
79324     getEditor: function(fieldInfo) {
79325         var me = this;
79326
79327         if (Ext.isNumber(fieldInfo)) {
79328             
79329             
79330             
79331             return me.query('>[isFormField]')[fieldInfo];
79332         } else if (fieldInfo instanceof Ext.grid.column.Column) {
79333             return fieldInfo.getEditor();
79334         }
79335     },
79336
79337     removeField: function(field) {
79338         var me = this;
79339
79340         
79341         field = me.getEditor(field);
79342         me.mun(field, 'validitychange', me.onValidityChange, me);
79343
79344         
79345         
79346         me.columns.removeKey(field.id);
79347     },
79348
79349     setField: function(column) {
79350         var me = this,
79351             field;
79352
79353         if (Ext.isArray(column)) {
79354             Ext.Array.forEach(column, me.setField, me);
79355             return;
79356         }
79357
79358         
79359         field = column.getEditor(null, {
79360             xtype: 'displayfield',
79361             
79362             
79363             getModelData: function() {
79364                 return null;
79365             }
79366         });
79367         field.margins = '0 0 0 2';
79368         field.setWidth(column.getDesiredWidth() - 2);
79369         me.mon(field, 'change', me.onFieldChange, me);
79370
79371         
79372         
79373         me.columns.add(field.id, column);
79374         if (column.hidden) {
79375             me.onColumnHide(column);
79376         }
79377         if (me.isVisible() && me.context) {
79378             me.renderColumnData(field, me.context.record);
79379         }
79380     },
79381
79382     loadRecord: function(record) {
79383         var me = this,
79384             form = me.getForm();
79385         form.loadRecord(record);
79386         if (form.isValid()) {
79387             me.hideToolTip();
79388         } else {
79389             me.showToolTip();
79390         }
79391
79392         
79393         Ext.Array.forEach(me.query('>displayfield'), function(field) {
79394             me.renderColumnData(field, record);
79395         }, me);
79396     },
79397
79398     renderColumnData: function(field, record) {
79399         var me = this,
79400             grid = me.editingPlugin.grid,
79401             headerCt = grid.headerCt,
79402             view = grid.view,
79403             store = view.store,
79404             column = me.columns.get(field.id),
79405             value = record.get(column.dataIndex);
79406
79407         
79408         if (column.renderer) {
79409             var metaData = { tdCls: '', style: '' },
79410                 rowIdx = store.indexOf(record),
79411                 colIdx = headerCt.getHeaderIndex(column);
79412
79413             value = column.renderer.call(
79414                 column.scope || headerCt.ownerCt,
79415                 value,
79416                 metaData,
79417                 record,
79418                 rowIdx,
79419                 colIdx,
79420                 store,
79421                 view
79422             );
79423         }
79424
79425         field.setRawValue(value);
79426         field.resetOriginalValue();
79427     },
79428
79429     beforeEdit: function() {
79430         var me = this;
79431
79432         if (me.isVisible() && !me.autoCancel && me.isDirty()) {
79433             me.showToolTip();
79434             return false;
79435         }
79436     },
79437
79438     
79439     startEdit: function(record, columnHeader) {
79440         var me = this,
79441             grid = me.editingPlugin.grid,
79442             view = grid.getView(),
79443             store = grid.store,
79444             context = me.context = Ext.apply(me.editingPlugin.context, {
79445                 view: grid.getView(),
79446                 store: store
79447             });
79448
79449         
79450         context.grid.getSelectionModel().select(record);
79451
79452         
79453         me.loadRecord(record);
79454
79455         if (!me.isVisible()) {
79456             me.show();
79457             me.focusContextCell();
79458         } else {
79459             me.reposition({
79460                 callback: this.focusContextCell
79461             });
79462         }
79463     },
79464
79465     
79466     focusContextCell: function() {
79467         var field = this.getEditor(this.context.colIdx);
79468         if (field && field.focus) {
79469             field.focus();
79470         }
79471     },
79472
79473     cancelEdit: function() {
79474         var me = this,
79475             form = me.getForm();
79476
79477         me.hide();
79478         form.clearInvalid();
79479         form.reset();
79480     },
79481
79482     completeEdit: function() {
79483         var me = this,
79484             form = me.getForm();
79485
79486         if (!form.isValid()) {
79487             return;
79488         }
79489
79490         form.updateRecord(me.context.record);
79491         me.hide();
79492         return true;
79493     },
79494
79495     onShow: function() {
79496         var me = this;
79497         me.callParent(arguments);
79498         me.reposition();
79499     },
79500
79501     onHide: function() {
79502         var me = this;
79503         me.callParent(arguments);
79504         me.hideToolTip();
79505         me.invalidateScroller();
79506         if (me.context) {
79507             me.context.view.focus();
79508             me.context = null;
79509         }
79510     },
79511
79512     isDirty: function() {
79513         var me = this,
79514             form = me.getForm();
79515         return form.isDirty();
79516     },
79517
79518     getToolTip: function() {
79519         var me = this,
79520             tip;
79521
79522         if (!me.tooltip) {
79523             tip = me.tooltip = Ext.createWidget('tooltip', {
79524                 cls: Ext.baseCSSPrefix + 'grid-row-editor-errors',
79525                 title: me.errorsText,
79526                 autoHide: false,
79527                 closable: true,
79528                 closeAction: 'disable',
79529                 anchor: 'left'
79530             });
79531         }
79532         return me.tooltip;
79533     },
79534
79535     hideToolTip: function() {
79536         var me = this,
79537             tip = me.getToolTip();
79538         if (tip.rendered) {
79539             tip.disable();
79540         }
79541         me.hiddenTip = false;
79542     },
79543
79544     showToolTip: function() {
79545         var me = this,
79546             tip = me.getToolTip(),
79547             context = me.context,
79548             row = Ext.get(context.row),
79549             viewEl = context.grid.view.el;
79550
79551         tip.setTarget(row);
79552         tip.showAt([-10000, -10000]);
79553         tip.body.update(me.getErrors());
79554         tip.mouseOffset = [viewEl.getWidth() - row.getWidth() + me.lastScrollLeft + 15, 0];
79555         me.repositionTip();
79556         tip.doLayout();
79557         tip.enable();
79558     },
79559
79560     repositionTip: function() {
79561         var me = this,
79562             tip = me.getToolTip(),
79563             context = me.context,
79564             row = Ext.get(context.row),
79565             viewEl = context.grid.view.el,
79566             viewHeight = viewEl.getHeight(),
79567             viewTop = me.lastScrollTop,
79568             viewBottom = viewTop + viewHeight,
79569             rowHeight = row.getHeight(),
79570             rowTop = row.dom.offsetTop,
79571             rowBottom = rowTop + rowHeight;
79572
79573         if (rowBottom > viewTop && rowTop < viewBottom) {
79574             tip.show();
79575             me.hiddenTip = false;
79576         } else {
79577             tip.hide();
79578             me.hiddenTip = true;
79579         }
79580     },
79581
79582     getErrors: function() {
79583         var me = this,
79584             dirtyText = !me.autoCancel && me.isDirty() ? me.dirtyText + '<br />' : '',
79585             errors = [];
79586
79587         Ext.Array.forEach(me.query('>[isFormField]'), function(field) {
79588             errors = errors.concat(
79589                 Ext.Array.map(field.getErrors(), function(e) {
79590                     return '<li>' + e + '</li>';
79591                 })
79592             );
79593         }, me);
79594
79595         return dirtyText + '<ul>' + errors.join('') + '</ul>';
79596     },
79597
79598     invalidateScroller: function() {
79599         var me = this,
79600             context = me.context,
79601             scroller = context.grid.verticalScroller;
79602
79603         if (scroller) {
79604             scroller.invalidate();
79605         }
79606     }
79607 });
79608
79609 Ext.define('Ext.grid.header.Container', {
79610     extend: 'Ext.container.Container',
79611     uses: [
79612         'Ext.grid.ColumnLayout',
79613         'Ext.grid.column.Column',
79614         'Ext.menu.Menu',
79615         'Ext.menu.CheckItem',
79616         'Ext.menu.Separator',
79617         'Ext.grid.plugin.HeaderResizer',
79618         'Ext.grid.plugin.HeaderReorderer'
79619     ],
79620     border: true,
79621
79622     alias: 'widget.headercontainer',
79623
79624     baseCls: Ext.baseCSSPrefix + 'grid-header-ct',
79625     dock: 'top',
79626
79627     
79628     weight: 100,
79629     defaultType: 'gridcolumn',
79630     
79631     defaultWidth: 100,
79632
79633
79634     sortAscText: 'Sort Ascending',
79635     sortDescText: 'Sort Descending',
79636     sortClearText: 'Clear Sort',
79637     columnsText: 'Columns',
79638
79639     lastHeaderCls: Ext.baseCSSPrefix + 'column-header-last',
79640     firstHeaderCls: Ext.baseCSSPrefix + 'column-header-first',
79641     headerOpenCls: Ext.baseCSSPrefix + 'column-header-open',
79642
79643     
79644     triStateSort: false,
79645
79646     ddLock: false,
79647
79648     dragging: false,
79649
79650     
79651
79652     
79653     sortable: true,
79654
79655     initComponent: function() {
79656         var me = this;
79657
79658         me.headerCounter = 0;
79659         me.plugins = me.plugins || [];
79660
79661         
79662         
79663
79664         
79665         
79666         if (!me.isHeader) {
79667             me.resizer   = Ext.create('Ext.grid.plugin.HeaderResizer');
79668             me.reorderer = Ext.create('Ext.grid.plugin.HeaderReorderer');
79669             if (!me.enableColumnResize) {
79670                 me.resizer.disable();
79671             }
79672             if (!me.enableColumnMove) {
79673                 me.reorderer.disable();
79674             }
79675             me.plugins.push(me.reorderer, me.resizer);
79676         }
79677
79678         
79679         if (me.isHeader && !me.items) {
79680             me.layout = 'auto';
79681         }
79682         
79683         else {
79684             me.layout = {
79685                 type: 'gridcolumn',
79686                 availableSpaceOffset: me.availableSpaceOffset,
79687                 align: 'stretchmax',
79688                 resetStretch: true
79689             };
79690         }
79691         me.defaults = me.defaults || {};
79692         Ext.applyIf(me.defaults, {
79693             width: me.defaultWidth,
79694             triStateSort: me.triStateSort,
79695             sortable: me.sortable
79696         });
79697         me.callParent();
79698         me.addEvents(
79699             
79700             'columnresize',
79701
79702             
79703             'headerclick',
79704
79705             
79706             'headertriggerclick',
79707
79708             
79709             'columnmove',
79710             
79711             'columnhide',
79712             
79713             'columnshow',
79714             
79715             'sortchange',
79716             
79717             'menucreate'
79718         );
79719     },
79720
79721     onDestroy: function() {
79722         Ext.destroy(this.resizer, this.reorderer);
79723         this.callParent();
79724     },
79725     
79726     applyDefaults: function(config){
79727         
79728         if (config && !config.isComponent && config.xtype == 'rownumberer') {
79729             return config;
79730         }
79731         return this.callParent([config]);
79732     },
79733
79734     applyColumnsState: function(columns) {
79735         if (!columns || !columns.length) {
79736             return;
79737         }
79738
79739         var me = this,
79740             i = 0,
79741             index,
79742             col;
79743
79744         Ext.each(columns, function (columnState) {
79745             col = me.down('gridcolumn[headerId=' + columnState.id + ']');
79746             if (col) {
79747                 index = me.items.indexOf(col);
79748                 if (i !== index) {
79749                     me.moveHeader(index, i);
79750                 }
79751
79752                 if (col.applyColumnState) {
79753                     col.applyColumnState(columnState);
79754                 }
79755                 ++i;
79756             }
79757         });
79758     },
79759
79760     getColumnsState: function () {
79761         var me = this,
79762             columns = [],
79763             state;
79764
79765         me.items.each(function (col) {
79766             state = col.getColumnState && col.getColumnState();
79767             if (state) {
79768                 columns.push(state);
79769             }
79770         });
79771
79772         return columns;
79773     },
79774
79775     
79776     
79777     
79778     onAdd: function(c) {
79779         var me = this;
79780         if (!c.headerId) {
79781             c.headerId = c.initialConfig.id || ('h' + (++me.headerCounter));
79782         }
79783         me.callParent(arguments);
79784         me.purgeCache();
79785     },
79786
79787     
79788     
79789     
79790     onRemove: function(c) {
79791         var me = this;
79792         me.callParent(arguments);
79793         me.purgeCache();
79794     },
79795
79796     afterRender: function() {
79797         this.callParent();
79798         var store   = this.up('[store]').store,
79799             sorters = store.sorters,
79800             first   = sorters.first(),
79801             hd;
79802
79803         if (first) {
79804             hd = this.down('gridcolumn[dataIndex=' + first.property  +']');
79805             if (hd) {
79806                 hd.setSortState(first.direction, false, true);
79807             }
79808         }
79809     },
79810
79811     afterLayout: function() {
79812         if (!this.isHeader) {
79813             var me = this,
79814                 topHeaders = me.query('>gridcolumn:not([hidden])'),
79815                 viewEl,
79816                 firstHeaderEl,
79817                 lastHeaderEl;
79818
79819             me.callParent(arguments);
79820
79821             if (topHeaders.length) {
79822                 firstHeaderEl = topHeaders[0].el;
79823                 if (firstHeaderEl !== me.pastFirstHeaderEl) {
79824                     if (me.pastFirstHeaderEl) {
79825                         me.pastFirstHeaderEl.removeCls(me.firstHeaderCls);
79826                     }
79827                     firstHeaderEl.addCls(me.firstHeaderCls);
79828                     me.pastFirstHeaderEl = firstHeaderEl;
79829                 }
79830
79831                 lastHeaderEl = topHeaders[topHeaders.length - 1].el;
79832                 if (lastHeaderEl !== me.pastLastHeaderEl) {
79833                     if (me.pastLastHeaderEl) {
79834                         me.pastLastHeaderEl.removeCls(me.lastHeaderCls);
79835                     }
79836                     lastHeaderEl.addCls(me.lastHeaderCls);
79837                     me.pastLastHeaderEl = lastHeaderEl;
79838                 }
79839             }
79840         }
79841
79842     },
79843
79844     onHeaderShow: function(header, preventLayout) {
79845         
79846         var me = this,
79847             gridSection = me.ownerCt,
79848             menu = me.getMenu(),
79849             topItems, topItemsVisible,
79850             colCheckItem,
79851             itemToEnable,
79852             len, i;
79853
79854         if (menu) {
79855
79856             colCheckItem = menu.down('menucheckitem[headerId=' + header.id + ']');
79857             if (colCheckItem) {
79858                 colCheckItem.setChecked(true, true);
79859             }
79860
79861             
79862             topItems = menu.query('#columnItem>menucheckitem[checked]');
79863             topItemsVisible = topItems.length;
79864             if ((me.getVisibleGridColumns().length > 1) && me.disabledMenuItems && me.disabledMenuItems.length) {
79865                 if (topItemsVisible == 1) {
79866                     Ext.Array.remove(me.disabledMenuItems, topItems[0]);
79867                 }
79868                 for (i = 0, len = me.disabledMenuItems.length; i < len; i++) {
79869                     itemToEnable = me.disabledMenuItems[i];
79870                     if (!itemToEnable.isDestroyed) {
79871                         itemToEnable[itemToEnable.menu ? 'enableCheckChange' : 'enable']();
79872                     }
79873                 }
79874                 if (topItemsVisible == 1) {
79875                     me.disabledMenuItems = topItems;
79876                 } else {
79877                     me.disabledMenuItems = [];
79878                 }
79879             }
79880         }
79881
79882         
79883         
79884         if (!header.isGroupHeader) {
79885             if (me.view) {
79886                 me.view.onHeaderShow(me, header, true);
79887             }
79888             if (gridSection) {
79889                 gridSection.onHeaderShow(me, header);
79890             }
79891         }
79892         me.fireEvent('columnshow', me, header);
79893
79894         
79895         if (preventLayout !== true) {
79896             me.doLayout();
79897         }
79898     },
79899
79900     doComponentLayout: function(){
79901         var me = this;
79902         if (me.view && me.view.saveScrollState) {
79903             me.view.saveScrollState();
79904         }
79905         me.callParent(arguments);
79906         if (me.view && me.view.restoreScrollState) {
79907             me.view.restoreScrollState();
79908         }
79909     },
79910
79911     onHeaderHide: function(header, suppressLayout) {
79912         
79913         var me = this,
79914             gridSection = me.ownerCt,
79915             menu = me.getMenu(),
79916             colCheckItem;
79917
79918         if (menu) {
79919
79920             
79921             colCheckItem = menu.down('menucheckitem[headerId=' + header.id + ']');
79922             if (colCheckItem) {
79923                 colCheckItem.setChecked(false, true);
79924             }
79925             me.setDisabledItems();
79926         }
79927
79928         
79929         if (!header.isGroupHeader) {
79930             if (me.view) {
79931                 me.view.onHeaderHide(me, header, true);
79932             }
79933             if (gridSection) {
79934                 gridSection.onHeaderHide(me, header);
79935             }
79936
79937             
79938             if (!suppressLayout) {
79939                 me.doLayout();
79940             }
79941         }
79942         me.fireEvent('columnhide', me, header);
79943     },
79944
79945     setDisabledItems: function(){
79946         var me = this,
79947             menu = me.getMenu(),
79948             i = 0,
79949             len,
79950             itemsToDisable,
79951             itemToDisable;
79952
79953         
79954         itemsToDisable = menu.query('#columnItem>menucheckitem[checked]');
79955         if ((itemsToDisable.length === 1)) {
79956             if (!me.disabledMenuItems) {
79957                 me.disabledMenuItems = [];
79958             }
79959
79960             
79961             if ((me.getVisibleGridColumns().length === 1) && itemsToDisable[0].menu) {
79962                 itemsToDisable = itemsToDisable.concat(itemsToDisable[0].menu.query('menucheckitem[checked]'));
79963             }
79964
79965             len = itemsToDisable.length;
79966             
79967             for (i = 0; i < len; i++) {
79968                 itemToDisable = itemsToDisable[i];
79969                 if (!Ext.Array.contains(me.disabledMenuItems, itemToDisable)) {
79970
79971                     
79972                     
79973                     itemToDisable.disabled = false;
79974                     itemToDisable[itemToDisable.menu ? 'disableCheckChange' : 'disable']();
79975                     me.disabledMenuItems.push(itemToDisable);
79976                 }
79977             }
79978         }
79979     },
79980
79981     
79982     tempLock: function() {
79983         this.ddLock = true;
79984         Ext.Function.defer(function() {
79985             this.ddLock = false;
79986         }, 200, this);
79987     },
79988
79989     onHeaderResize: function(header, w, suppressFocus) {
79990         this.tempLock();
79991         if (this.view && this.view.rendered) {
79992             this.view.onHeaderResize(header, w, suppressFocus);
79993         }
79994     },
79995
79996     onHeaderClick: function(header, e, t) {
79997         this.fireEvent("headerclick", this, header, e, t);
79998     },
79999
80000     onHeaderTriggerClick: function(header, e, t) {
80001         
80002         if (this.fireEvent("headertriggerclick", this, header, e, t) !== false) {
80003             this.showMenuBy(t, header);
80004         }
80005     },
80006
80007     showMenuBy: function(t, header) {
80008         var menu = this.getMenu(),
80009             ascItem  = menu.down('#ascItem'),
80010             descItem = menu.down('#descItem'),
80011             sortableMth;
80012
80013         menu.activeHeader = menu.ownerCt = header;
80014         menu.setFloatParent(header);
80015         
80016         header.titleContainer.addCls(this.headerOpenCls);
80017
80018         
80019         sortableMth = header.sortable ? 'enable' : 'disable';
80020         if (ascItem) {
80021             ascItem[sortableMth]();
80022         }
80023         if (descItem) {
80024             descItem[sortableMth]();
80025         }
80026         menu.showBy(t);
80027     },
80028
80029     
80030     onMenuDeactivate: function() {
80031         var menu = this.getMenu();
80032         
80033         menu.activeHeader.titleContainer.removeCls(this.headerOpenCls);
80034     },
80035
80036     moveHeader: function(fromIdx, toIdx) {
80037
80038         
80039         this.tempLock();
80040         this.onHeaderMoved(this.move(fromIdx, toIdx), fromIdx, toIdx);
80041     },
80042
80043     purgeCache: function() {
80044         var me = this;
80045         
80046         delete me.gridDataColumns;
80047         delete me.hideableColumns;
80048
80049         
80050         if (me.menu) {
80051             me.menu.destroy();
80052             delete me.menu;
80053         }
80054     },
80055
80056     onHeaderMoved: function(header, fromIdx, toIdx) {
80057         var me = this,
80058             gridSection = me.ownerCt;
80059
80060         if (gridSection && gridSection.onHeaderMove) {
80061             gridSection.onHeaderMove(me, header, fromIdx, toIdx);
80062         }
80063         me.fireEvent("columnmove", me, header, fromIdx, toIdx);
80064     },
80065
80066     
80067     getMenu: function() {
80068         var me = this;
80069
80070         if (!me.menu) {
80071             me.menu = Ext.create('Ext.menu.Menu', {
80072                 hideOnParentHide: false,  
80073                 items: me.getMenuItems(),
80074                 listeners: {
80075                     deactivate: me.onMenuDeactivate,
80076                     scope: me
80077                 }
80078             });
80079             me.setDisabledItems();
80080             me.fireEvent('menucreate', me, me.menu);
80081         }
80082         return me.menu;
80083     },
80084
80085     
80086     getMenuItems: function() {
80087         var me = this,
80088             menuItems = [],
80089             hideableColumns = me.enableColumnHide ? me.getColumnMenu(me) : null;
80090
80091         if (me.sortable) {
80092             menuItems = [{
80093                 itemId: 'ascItem',
80094                 text: me.sortAscText,
80095                 cls: Ext.baseCSSPrefix + 'hmenu-sort-asc',
80096                 handler: me.onSortAscClick,
80097                 scope: me
80098             },{
80099                 itemId: 'descItem',
80100                 text: me.sortDescText,
80101                 cls: Ext.baseCSSPrefix + 'hmenu-sort-desc',
80102                 handler: me.onSortDescClick,
80103                 scope: me
80104             }];
80105         }
80106         if (hideableColumns && hideableColumns.length) {
80107             menuItems.push('-', {
80108                 itemId: 'columnItem',
80109                 text: me.columnsText,
80110                 cls: Ext.baseCSSPrefix + 'cols-icon',
80111                 menu: hideableColumns
80112             });
80113         }
80114         return menuItems;
80115     },
80116
80117     
80118     onSortAscClick: function() {
80119         var menu = this.getMenu(),
80120             activeHeader = menu.activeHeader;
80121
80122         activeHeader.setSortState('ASC');
80123     },
80124
80125     
80126     onSortDescClick: function() {
80127         var menu = this.getMenu(),
80128             activeHeader = menu.activeHeader;
80129
80130         activeHeader.setSortState('DESC');
80131     },
80132
80133     
80134     getColumnMenu: function(headerContainer) {
80135         var menuItems = [],
80136             i = 0,
80137             item,
80138             items = headerContainer.query('>gridcolumn[hideable]'),
80139             itemsLn = items.length,
80140             menuItem;
80141
80142         for (; i < itemsLn; i++) {
80143             item = items[i];
80144             menuItem = Ext.create('Ext.menu.CheckItem', {
80145                 text: item.text,
80146                 checked: !item.hidden,
80147                 hideOnClick: false,
80148                 headerId: item.id,
80149                 menu: item.isGroupHeader ? this.getColumnMenu(item) : undefined,
80150                 checkHandler: this.onColumnCheckChange,
80151                 scope: this
80152             });
80153             if (itemsLn === 1) {
80154                 menuItem.disabled = true;
80155             }
80156             menuItems.push(menuItem);
80157
80158             
80159             
80160             item.on({
80161                 destroy: Ext.Function.bind(menuItem.destroy, menuItem)
80162             });
80163         }
80164         return menuItems;
80165     },
80166
80167     onColumnCheckChange: function(checkItem, checked) {
80168         var header = Ext.getCmp(checkItem.headerId);
80169         header[checked ? 'show' : 'hide']();
80170     },
80171
80172     
80173     getColumnsForTpl: function(flushCache) {
80174         var cols    = [],
80175             headers   = this.getGridColumns(flushCache),
80176             headersLn = headers.length,
80177             i = 0,
80178             header,
80179             width;
80180
80181         for (; i < headersLn; i++) {
80182             header = headers[i];
80183
80184             if (header.hidden || header.up('headercontainer[hidden=true]')) {
80185                 width = 0;
80186             } else {
80187                 width = header.getDesiredWidth();
80188                 
80189                 
80190                 
80191                 if ((i === 0) && (Ext.isIE6 || Ext.isIE7)) {
80192                     width += 1;
80193                 }
80194             }
80195             cols.push({
80196                 dataIndex: header.dataIndex,
80197                 align: header.align,
80198                 width: width,
80199                 id: header.id,
80200                 cls: header.tdCls,
80201                 columnId: header.getItemId()
80202             });
80203         }
80204         return cols;
80205     },
80206
80207     
80208     getColumnCount: function() {
80209         return this.getGridColumns().length;
80210     },
80211
80212     
80213     getFullWidth: function(flushCache) {
80214         var fullWidth = 0,
80215             headers     = this.getVisibleGridColumns(flushCache),
80216             headersLn   = headers.length,
80217             i         = 0;
80218
80219         for (; i < headersLn; i++) {
80220             if (!isNaN(headers[i].width)) {
80221                 
80222                 if (headers[i].getDesiredWidth) {
80223                     fullWidth += headers[i].getDesiredWidth();
80224                 
80225                 } else {
80226                     fullWidth += headers[i].getWidth();
80227                 }
80228             }
80229         }
80230         return fullWidth;
80231     },
80232
80233     
80234     clearOtherSortStates: function(activeHeader) {
80235         var headers   = this.getGridColumns(),
80236             headersLn = headers.length,
80237             i         = 0,
80238             oldSortState;
80239
80240         for (; i < headersLn; i++) {
80241             if (headers[i] !== activeHeader) {
80242                 oldSortState = headers[i].sortState;
80243                 
80244                 headers[i].setSortState(null, true);
80245                 
80246                 
80247                 
80248             }
80249         }
80250     },
80251
80252     
80253     getVisibleGridColumns: function(refreshCache) {
80254         return Ext.ComponentQuery.query(':not([hidden])', this.getGridColumns(refreshCache));
80255     },
80256
80257     
80258     getGridColumns: function(refreshCache) {
80259         var me = this,
80260             result = refreshCache ? null : me.gridDataColumns;
80261
80262         
80263         if (!result) {
80264             me.gridDataColumns = result = [];
80265             me.cascade(function(c) {
80266                 if ((c !== me) && !c.isGroupHeader) {
80267                     result.push(c);
80268                 }
80269             });
80270         }
80271
80272         return result;
80273     },
80274
80275     
80276     getHideableColumns: function(refreshCache) {
80277         var me = this,
80278             result = refreshCache ? null : me.hideableColumns;
80279
80280         if (!result) {
80281             result = me.hideableColumns = me.query('[hideable]');
80282         }
80283         return result;
80284     },
80285
80286     
80287     getHeaderIndex: function(header) {
80288         var columns = this.getGridColumns();
80289         return Ext.Array.indexOf(columns, header);
80290     },
80291
80292     
80293     getHeaderAtIndex: function(index) {
80294         var columns = this.getGridColumns();
80295         return columns[index];
80296     },
80297
80298     
80299     prepareData: function(data, rowIdx, record, view, panel) {
80300         var obj       = {},
80301             headers   = this.gridDataColumns || this.getGridColumns(),
80302             headersLn = headers.length,
80303             colIdx    = 0,
80304             header,
80305             headerId,
80306             renderer,
80307             value,
80308             metaData,
80309             store = panel.store;
80310
80311         for (; colIdx < headersLn; colIdx++) {
80312             metaData = {
80313                 tdCls: '',
80314                 style: ''
80315             };
80316             header = headers[colIdx];
80317             headerId = header.id;
80318             renderer = header.renderer;
80319             value = data[header.dataIndex];
80320
80321             
80322             
80323             if (typeof renderer === "string") {
80324                 header.renderer = renderer = Ext.util.Format[renderer];
80325             }
80326
80327             if (typeof renderer === "function") {
80328                 value = renderer.call(
80329                     header.scope || this.ownerCt,
80330                     value,
80331                     
80332                     
80333                     metaData,
80334                     record,
80335                     rowIdx,
80336                     colIdx,
80337                     store,
80338                     view
80339                 );
80340             }
80341
80342
80343             obj[headerId+'-modified'] = record.isModified(header.dataIndex) ? Ext.baseCSSPrefix + 'grid-dirty-cell' : '';
80344             obj[headerId+'-tdCls'] = metaData.tdCls;
80345             obj[headerId+'-tdAttr'] = metaData.tdAttr;
80346             obj[headerId+'-style'] = metaData.style;
80347             if (value === undefined || value === null || value === '') {
80348                 value = '&#160;';
80349             }
80350             obj[headerId] = value;
80351         }
80352         return obj;
80353     },
80354
80355     expandToFit: function(header) {
80356         if (this.view) {
80357             this.view.expandToFit(header);
80358         }
80359     }
80360 });
80361
80362
80363 Ext.define('Ext.grid.column.Column', {
80364     extend: 'Ext.grid.header.Container',
80365     alias: 'widget.gridcolumn',
80366     requires: ['Ext.util.KeyNav'],
80367     alternateClassName: 'Ext.grid.Column',
80368
80369     baseCls: Ext.baseCSSPrefix + 'column-header ' + Ext.baseCSSPrefix + 'unselectable',
80370
80371     
80372     hoverCls: Ext.baseCSSPrefix + 'column-header-over',
80373
80374     handleWidth: 5,
80375
80376     sortState: null,
80377
80378     possibleSortStates: ['ASC', 'DESC'],
80379
80380     renderTpl:
80381         '<div id="{id}-titleContainer" class="' + Ext.baseCSSPrefix + 'column-header-inner">' +
80382             '<span id="{id}-textEl" class="' + Ext.baseCSSPrefix + 'column-header-text">' +
80383                 '{text}' +
80384             '</span>' +
80385             '<tpl if="!values.menuDisabled">'+
80386                 '<div id="{id}-triggerEl" class="' + Ext.baseCSSPrefix + 'column-header-trigger"></div>'+
80387             '</tpl>' +
80388         '</div>',
80389
80390     
80391
80392     
80393     dataIndex: null,
80394
80395     
80396     text: '&#160;',
80397
80398     
80399     sortable: true,
80400
80401     
80402
80403     
80404
80405     
80406
80407     
80408     hideable: true,
80409
80410     
80411     menuDisabled: false,
80412
80413     
80414     renderer: false,
80415
80416     
80417     align: 'left',
80418
80419     
80420     draggable: true,
80421
80422     
80423     
80424     initDraggable: Ext.emptyFn,
80425
80426     
80427
80428     
80429
80430     
80431
80432     
80433
80434     
80435
80436     
80437     isHeader: true,
80438
80439     initComponent: function() {
80440         var me = this,
80441             i,
80442             len,
80443             item;
80444
80445         if (Ext.isDefined(me.header)) {
80446             me.text = me.header;
80447             delete me.header;
80448         }
80449
80450         
80451         
80452         
80453         if (me.flex) {
80454             me.minWidth = me.minWidth || Ext.grid.plugin.HeaderResizer.prototype.minColWidth;
80455         }
80456         
80457         
80458         else {
80459             me.minWidth = me.width;
80460         }
80461
80462         if (!me.triStateSort) {
80463             me.possibleSortStates.length = 2;
80464         }
80465
80466         
80467         if (Ext.isDefined(me.columns)) {
80468             me.isGroupHeader = true;
80469
80470
80471             
80472             me.items = me.columns;
80473             delete me.columns;
80474             delete me.flex;
80475             me.width = 0;
80476
80477             
80478             for (i = 0, len = me.items.length; i < len; i++) {
80479                 item = me.items[i];
80480                 if (!item.hidden) {
80481                     me.width += item.width || Ext.grid.header.Container.prototype.defaultWidth;
80482                 }
80483             }
80484             me.minWidth = me.width;
80485
80486             me.cls = (me.cls||'') + ' ' + Ext.baseCSSPrefix + 'group-header';
80487             me.sortable = false;
80488             me.resizable = false;
80489             me.align = 'center';
80490         }
80491
80492         me.addChildEls('titleContainer', 'triggerEl', 'textEl');
80493
80494         
80495         me.callParent(arguments);
80496     },
80497
80498     onAdd: function(childHeader) {
80499         childHeader.isSubHeader = true;
80500         childHeader.addCls(Ext.baseCSSPrefix + 'group-sub-header');
80501         this.callParent(arguments);
80502     },
80503
80504     onRemove: function(childHeader) {
80505         childHeader.isSubHeader = false;
80506         childHeader.removeCls(Ext.baseCSSPrefix + 'group-sub-header');
80507         this.callParent(arguments);
80508     },
80509
80510     initRenderData: function() {
80511         var me = this;
80512
80513         Ext.applyIf(me.renderData, {
80514             text: me.text,
80515             menuDisabled: me.menuDisabled
80516         });
80517         return me.callParent(arguments);
80518     },
80519
80520     applyColumnState: function (state) {
80521         var me = this,
80522             defined = Ext.isDefined;
80523             
80524         
80525         me.applyColumnsState(state.columns);
80526
80527         
80528         
80529         if (defined(state.hidden)) {
80530             me.hidden = state.hidden;
80531         }
80532         if (defined(state.locked)) {
80533             me.locked = state.locked;
80534         }
80535         if (defined(state.sortable)) {
80536             me.sortable = state.sortable;
80537         }
80538         if (defined(state.width)) {
80539             delete me.flex;
80540             me.width = state.width;
80541         } else if (defined(state.flex)) {
80542             delete me.width;
80543             me.flex = state.flex;
80544         }
80545     },
80546
80547     getColumnState: function () {
80548         var me = this,
80549             columns = [],
80550             state = {
80551                 id: me.headerId
80552             };
80553
80554         me.savePropsToState(['hidden', 'sortable', 'locked', 'flex', 'width'], state);
80555         
80556         if (me.isGroupHeader) {
80557             me.items.each(function(column){
80558                 columns.push(column.getColumnState());
80559             });
80560             if (columns.length) {
80561                 state.columns = columns;
80562             }
80563         } else if (me.isSubHeader && me.ownerCt.hidden) {
80564             
80565             delete me.hidden;
80566         }
80567
80568         if ('width' in state) {
80569             delete state.flex; 
80570         }
80571         return state;
80572     },
80573
80574     
80575     setText: function(text) {
80576         this.text = text;
80577         if (this.rendered) {
80578             this.textEl.update(text);
80579         }
80580     },
80581
80582     
80583     
80584     getOwnerHeaderCt: function() {
80585         return this.up(':not([isHeader])');
80586     },
80587
80588     
80589     getIndex: function() {
80590         return this.isGroupColumn ? false : this.getOwnerHeaderCt().getHeaderIndex(this);
80591     },
80592
80593     onRender: function() {
80594         var me = this,
80595             grid = me.up('tablepanel');
80596
80597         
80598         
80599         if (grid && (!me.sortable || grid.sortableColumns === false) && !me.groupable && !me.lockable && (grid.enableColumnHide === false || !me.getOwnerHeaderCt().getHideableColumns().length)) {
80600             me.menuDisabled = true;
80601         }
80602         me.callParent(arguments);
80603     },
80604
80605     afterRender: function() {
80606         var me = this,
80607             el = me.el;
80608
80609         me.callParent(arguments);
80610
80611         el.addCls(Ext.baseCSSPrefix + 'column-header-align-' + me.align).addClsOnOver(me.overCls);
80612
80613         me.mon(el, {
80614             click:     me.onElClick,
80615             dblclick:  me.onElDblClick,
80616             scope:     me
80617         });
80618
80619         
80620         
80621         if (!Ext.isIE8 || !Ext.isStrict) {
80622             me.mon(me.getFocusEl(), {
80623                 focus: me.onTitleMouseOver,
80624                 blur: me.onTitleMouseOut,
80625                 scope: me
80626             });
80627         }
80628
80629         me.mon(me.titleContainer, {
80630             mouseenter:  me.onTitleMouseOver,
80631             mouseleave:  me.onTitleMouseOut,
80632             scope:      me
80633         });
80634
80635         me.keyNav = Ext.create('Ext.util.KeyNav', el, {
80636             enter: me.onEnterKey,
80637             down: me.onDownKey,
80638             scope: me
80639         });
80640     },
80641
80642     
80643     setWidth: function(width,  doLayout) {
80644         var me = this,
80645             headerCt = me.ownerCt,
80646             siblings,
80647             len, i,
80648             oldWidth = me.getWidth(),
80649             groupWidth = 0,
80650             sibling;
80651
80652         if (width !== oldWidth) {
80653             me.oldWidth = oldWidth;
80654
80655             
80656             
80657             me.minWidth = me.width = width;
80658
80659             
80660             if (headerCt.isGroupHeader) {
80661                 siblings = headerCt.items.items;
80662                 len = siblings.length;
80663
80664                 for (i = 0; i < len; i++) {
80665                     sibling = siblings[i];
80666                     if (!sibling.hidden) {
80667                         groupWidth += (sibling === me) ? width : sibling.getWidth();
80668                     }
80669                 }
80670                 headerCt.setWidth(groupWidth, doLayout);
80671             } else if (doLayout !== false) {
80672                 
80673                 headerCt.doLayout();
80674             }
80675         }
80676     },
80677
80678     afterComponentLayout: function(width, height) {
80679         var me = this,
80680             ownerHeaderCt = this.getOwnerHeaderCt();
80681
80682         me.callParent(arguments);
80683
80684         
80685         
80686         
80687         if (width && !me.isGroupHeader && ownerHeaderCt) {
80688             ownerHeaderCt.onHeaderResize(me, width, true);
80689         }
80690         if (me.oldWidth && (width !== me.oldWidth)) {
80691             ownerHeaderCt.fireEvent('columnresize', ownerHeaderCt, this, width);
80692         }
80693         delete me.oldWidth;
80694     },
80695
80696     
80697     
80698     
80699     setPadding: function(headerHeight) {
80700         var me = this,
80701             lineHeight = Ext.util.TextMetrics.measure(me.textEl.dom, me.text).height;
80702
80703         
80704         if (!me.isGroupHeader) {
80705             if (me.titleContainer.getHeight() < headerHeight) {
80706                 me.titleContainer.dom.style.height = headerHeight + 'px';
80707             }
80708         }
80709         headerHeight = me.titleContainer.getViewSize().height;
80710
80711         
80712         if (lineHeight) {
80713             me.titleContainer.setStyle({
80714                 paddingTop: Math.max(((headerHeight - lineHeight) / 2), 0) + 'px'
80715             });
80716         }
80717
80718         
80719         if (Ext.isIE && me.triggerEl) {
80720             me.triggerEl.setHeight(headerHeight);
80721         }
80722     },
80723
80724     onDestroy: function() {
80725         var me = this;
80726         
80727         Ext.destroy(me.textEl, me.keyNav);
80728         delete me.keyNav;
80729         me.callParent(arguments);
80730     },
80731
80732     onTitleMouseOver: function() {
80733         this.titleContainer.addCls(this.hoverCls);
80734     },
80735
80736     onTitleMouseOut: function() {
80737         this.titleContainer.removeCls(this.hoverCls);
80738     },
80739
80740     onDownKey: function(e) {
80741         if (this.triggerEl) {
80742             this.onElClick(e, this.triggerEl.dom || this.el.dom);
80743         }
80744     },
80745
80746     onEnterKey: function(e) {
80747         this.onElClick(e, this.el.dom);
80748     },
80749
80750     
80751     onElDblClick: function(e, t) {
80752         var me = this,
80753             ownerCt = me.ownerCt;
80754         if (ownerCt && Ext.Array.indexOf(ownerCt.items, me) !== 0 && me.isOnLeftEdge(e) ) {
80755             ownerCt.expandToFit(me.previousSibling('gridcolumn'));
80756         }
80757     },
80758
80759     onElClick: function(e, t) {
80760
80761         
80762         var me = this,
80763             ownerHeaderCt = me.getOwnerHeaderCt();
80764
80765         if (ownerHeaderCt && !ownerHeaderCt.ddLock) {
80766             
80767             
80768             if (me.triggerEl && (e.target === me.triggerEl.dom || t === me.triggerEl.dom || e.within(me.triggerEl))) {
80769                 ownerHeaderCt.onHeaderTriggerClick(me, e, t);
80770             
80771             } else if (e.getKey() || (!me.isOnLeftEdge(e) && !me.isOnRightEdge(e))) {
80772                 me.toggleSortState();
80773                 ownerHeaderCt.onHeaderClick(me, e, t);
80774             }
80775         }
80776     },
80777
80778     
80779     processEvent: function(type, view, cell, recordIndex, cellIndex, e) {
80780         return this.fireEvent.apply(this, arguments);
80781     },
80782
80783     toggleSortState: function() {
80784         var me = this,
80785             idx,
80786             nextIdx;
80787
80788         if (me.sortable) {
80789             idx = Ext.Array.indexOf(me.possibleSortStates, me.sortState);
80790
80791             nextIdx = (idx + 1) % me.possibleSortStates.length;
80792             me.setSortState(me.possibleSortStates[nextIdx]);
80793         }
80794     },
80795
80796     doSort: function(state) {
80797         var ds = this.up('tablepanel').store;
80798         ds.sort({
80799             property: this.getSortParam(),
80800             direction: state
80801         });
80802     },
80803
80804     
80805     getSortParam: function() {
80806         return this.dataIndex;
80807     },
80808
80809     
80810     
80811     setSortState: function(state, skipClear, initial) {
80812         var me = this,
80813             colSortClsPrefix = Ext.baseCSSPrefix + 'column-header-sort-',
80814             ascCls = colSortClsPrefix + 'ASC',
80815             descCls = colSortClsPrefix + 'DESC',
80816             nullCls = colSortClsPrefix + 'null',
80817             ownerHeaderCt = me.getOwnerHeaderCt(),
80818             oldSortState = me.sortState;
80819
80820         if (oldSortState !== state && me.getSortParam()) {
80821             me.addCls(colSortClsPrefix + state);
80822             
80823             if (state && !initial) {
80824                 me.doSort(state);
80825             }
80826             switch (state) {
80827                 case 'DESC':
80828                     me.removeCls([ascCls, nullCls]);
80829                     break;
80830                 case 'ASC':
80831                     me.removeCls([descCls, nullCls]);
80832                     break;
80833                 case null:
80834                     me.removeCls([ascCls, descCls]);
80835                     break;
80836             }
80837             if (ownerHeaderCt && !me.triStateSort && !skipClear) {
80838                 ownerHeaderCt.clearOtherSortStates(me);
80839             }
80840             me.sortState = state;
80841             ownerHeaderCt.fireEvent('sortchange', ownerHeaderCt, me, state);
80842         }
80843     },
80844
80845     hide: function() {
80846         var me = this,
80847             items,
80848             len, i,
80849             lb,
80850             newWidth = 0,
80851             ownerHeaderCt = me.getOwnerHeaderCt();
80852
80853         
80854         me.oldWidth = me.getWidth();
80855
80856         
80857         if (me.isGroupHeader) {
80858             items = me.items.items;
80859             me.callParent(arguments);
80860             ownerHeaderCt.onHeaderHide(me);
80861             for (i = 0, len = items.length; i < len; i++) {
80862                 items[i].hidden = true;
80863                 ownerHeaderCt.onHeaderHide(items[i], true);
80864             }
80865             return;
80866         }
80867
80868         
80869         lb = me.ownerCt.componentLayout.layoutBusy;
80870         me.ownerCt.componentLayout.layoutBusy = true;
80871         me.callParent(arguments);
80872         me.ownerCt.componentLayout.layoutBusy = lb;
80873
80874         
80875         ownerHeaderCt.onHeaderHide(me);
80876
80877         if (me.ownerCt.isGroupHeader) {
80878             
80879             items = me.ownerCt.query('>:not([hidden])');
80880             if (!items.length) {
80881                 me.ownerCt.hide();
80882             }
80883             
80884             else {
80885                 for (i = 0, len = items.length; i < len; i++) {
80886                     newWidth += items[i].getWidth();
80887                 }
80888                 me.ownerCt.minWidth = newWidth;
80889                 me.ownerCt.setWidth(newWidth);
80890             }
80891         }
80892     },
80893
80894     show: function() {
80895         var me = this,
80896             ownerCt = me.ownerCt,
80897             ownerCtCompLayout = ownerCt.componentLayout,
80898             ownerCtCompLayoutBusy = ownerCtCompLayout.layoutBusy,
80899             ownerCtLayout = ownerCt.layout,
80900             ownerCtLayoutBusy = ownerCtLayout.layoutBusy,
80901             items,
80902             len, i,
80903             item,
80904             newWidth = 0;
80905
80906         
80907
80908         
80909         ownerCtCompLayout.layoutBusy = ownerCtLayout.layoutBusy = true;
80910
80911         me.callParent(arguments);
80912
80913         ownerCtCompLayout.layoutBusy = ownerCtCompLayoutBusy;
80914         ownerCtLayout.layoutBusy = ownerCtLayoutBusy;
80915
80916         
80917         if (me.isSubHeader) {
80918             if (!ownerCt.isVisible()) {
80919                 ownerCt.show();
80920             }
80921         }
80922
80923         
80924         if (me.isGroupHeader && !me.query(':not([hidden])').length) {
80925             items = me.query('>*');
80926             for (i = 0, len = items.length; i < len; i++) {
80927                 item = items[i];
80928                 item.preventLayout = true;
80929                 item.show();
80930                 newWidth += item.getWidth();
80931                 delete item.preventLayout;
80932             }
80933             me.setWidth(newWidth);
80934         }
80935
80936         
80937         if (ownerCt.isGroupHeader && me.preventLayout !== true) {
80938             items = ownerCt.query('>:not([hidden])');
80939             for (i = 0, len = items.length; i < len; i++) {
80940                 newWidth += items[i].getWidth();
80941             }
80942             ownerCt.minWidth = newWidth;
80943             ownerCt.setWidth(newWidth);
80944         }
80945
80946         
80947         ownerCt = me.getOwnerHeaderCt();
80948         if (ownerCt) {
80949             ownerCt.onHeaderShow(me, me.preventLayout);
80950         }
80951     },
80952
80953     getDesiredWidth: function() {
80954         var me = this;
80955         if (me.rendered && me.componentLayout && me.componentLayout.lastComponentSize) {
80956             
80957             
80958             
80959             
80960             
80961             
80962             return me.componentLayout.lastComponentSize.width;
80963         
80964         
80965         
80966         }
80967         else if (me.flex) {
80968             
80969             return me.width;
80970         }
80971         else {
80972             return me.width;
80973         }
80974     },
80975
80976     getCellSelector: function() {
80977         return '.' + Ext.baseCSSPrefix + 'grid-cell-' + this.getItemId();
80978     },
80979
80980     getCellInnerSelector: function() {
80981         return this.getCellSelector() + ' .' + Ext.baseCSSPrefix + 'grid-cell-inner';
80982     },
80983
80984     isOnLeftEdge: function(e) {
80985         return (e.getXY()[0] - this.el.getLeft() <= this.handleWidth);
80986     },
80987
80988     isOnRightEdge: function(e) {
80989         return (this.el.getRight() - e.getXY()[0] <= this.handleWidth);
80990     }
80991
80992     
80993     
80994
80995     
80996     
80997 });
80998
80999
81000 Ext.define('Ext.grid.RowNumberer', {
81001     extend: 'Ext.grid.column.Column',
81002     alias: 'widget.rownumberer',
81003
81004     
81005     text: "&#160",
81006
81007     
81008     width: 23,
81009
81010     
81011     sortable: false,
81012
81013     align: 'right',
81014
81015     constructor : function(config){
81016         this.callParent(arguments);
81017         if (this.rowspan) {
81018             this.renderer = Ext.Function.bind(this.renderer, this);
81019         }
81020     },
81021
81022     
81023     resizable: false,
81024     hideable: false,
81025     menuDisabled: true,
81026     dataIndex: '',
81027     cls: Ext.baseCSSPrefix + 'row-numberer',
81028     rowspan: undefined,
81029
81030     
81031     renderer: function(value, metaData, record, rowIdx, colIdx, store) {
81032         if (this.rowspan){
81033             metaData.cellAttr = 'rowspan="'+this.rowspan+'"';
81034         }
81035
81036         metaData.tdCls = Ext.baseCSSPrefix + 'grid-cell-special';
81037         return store.indexOfTotal(record) + 1;
81038     }
81039 });
81040
81041
81042 Ext.define('Ext.view.DropZone', {
81043     extend: 'Ext.dd.DropZone',
81044
81045     indicatorHtml: '<div class="x-grid-drop-indicator-left"></div><div class="x-grid-drop-indicator-right"></div>',
81046     indicatorCls: 'x-grid-drop-indicator',
81047
81048     constructor: function(config) {
81049         var me = this;
81050         Ext.apply(me, config);
81051
81052         
81053         
81054         
81055         
81056         
81057         if (!me.ddGroup) {
81058             me.ddGroup = 'view-dd-zone-' + me.view.id;
81059         }
81060
81061         
81062         
81063         
81064         me.callParent([me.view.el]);
81065     },
81066
81067
81068
81069     fireViewEvent: function() {
81070         var me = this,
81071             result;
81072
81073         me.lock();
81074         result = me.view.fireEvent.apply(me.view, arguments);
81075         me.unlock();
81076         return result;
81077     },
81078
81079     getTargetFromEvent : function(e) {
81080         var node = e.getTarget(this.view.getItemSelector()),
81081             mouseY, nodeList, testNode, i, len, box;
81082
81083
81084
81085         if (!node) {
81086             mouseY = e.getPageY();
81087             for (i = 0, nodeList = this.view.getNodes(), len = nodeList.length; i < len; i++) {
81088                 testNode = nodeList[i];
81089                 box = Ext.fly(testNode).getBox();
81090                 if (mouseY <= box.bottom) {
81091                     return testNode;
81092                 }
81093             }
81094         }
81095         return node;
81096     },
81097
81098     getIndicator: function() {
81099         var me = this;
81100
81101         if (!me.indicator) {
81102             me.indicator = Ext.createWidget('component', {
81103                 html: me.indicatorHtml,
81104                 cls: me.indicatorCls,
81105                 ownerCt: me.view,
81106                 floating: true,
81107                 shadow: false
81108             });
81109         }
81110         return me.indicator;
81111     },
81112
81113     getPosition: function(e, node) {
81114         var y      = e.getXY()[1],
81115             region = Ext.fly(node).getRegion(),
81116             pos;
81117
81118         if ((region.bottom - y) >= (region.bottom - region.top) / 2) {
81119             pos = "before";
81120         } else {
81121             pos = "after";
81122         }
81123         return pos;
81124     },
81125
81126     
81127     containsRecordAtOffset: function(records, record, offset) {
81128         if (!record) {
81129             return false;
81130         }
81131         var view = this.view,
81132             recordIndex = view.indexOf(record),
81133             nodeBefore = view.getNode(recordIndex + offset),
81134             recordBefore = nodeBefore ? view.getRecord(nodeBefore) : null;
81135
81136         return recordBefore && Ext.Array.contains(records, recordBefore);
81137     },
81138
81139     positionIndicator: function(node, data, e) {
81140         var me = this,
81141             view = me.view,
81142             pos = me.getPosition(e, node),
81143             overRecord = view.getRecord(node),
81144             draggingRecords = data.records,
81145             indicator, indicatorY;
81146
81147         if (!Ext.Array.contains(draggingRecords, overRecord) && (
81148             pos == 'before' && !me.containsRecordAtOffset(draggingRecords, overRecord, -1) ||
81149             pos == 'after' && !me.containsRecordAtOffset(draggingRecords, overRecord, 1)
81150         )) {
81151             me.valid = true;
81152
81153             if (me.overRecord != overRecord || me.currentPosition != pos) {
81154
81155                 indicatorY = Ext.fly(node).getY() - view.el.getY() - 1;
81156                 if (pos == 'after') {
81157                     indicatorY += Ext.fly(node).getHeight();
81158                 }
81159                 me.getIndicator().setWidth(Ext.fly(view.el).getWidth()).showAt(0, indicatorY);
81160
81161                 
81162                 me.overRecord = overRecord;
81163                 me.currentPosition = pos;
81164             }
81165         } else {
81166             me.invalidateDrop();
81167         }
81168     },
81169
81170     invalidateDrop: function() {
81171         if (this.valid) {
81172             this.valid = false;
81173             this.getIndicator().hide();
81174         }
81175     },
81176
81177     
81178     onNodeOver: function(node, dragZone, e, data) {
81179         var me = this;
81180
81181         if (!Ext.Array.contains(data.records, me.view.getRecord(node))) {
81182             me.positionIndicator(node, data, e);
81183         }
81184         return me.valid ? me.dropAllowed : me.dropNotAllowed;
81185     },
81186
81187     
81188     
81189     notifyOut: function(node, dragZone, e, data) {
81190         var me = this;
81191
81192         me.callParent(arguments);
81193         delete me.overRecord;
81194         delete me.currentPosition;
81195         if (me.indicator) {
81196             me.indicator.hide();
81197         }
81198     },
81199
81200     
81201     onContainerOver : function(dd, e, data) {
81202         var me = this,
81203             view = me.view,
81204             count = view.store.getCount();
81205
81206         
81207         if (count) {
81208             me.positionIndicator(view.getNode(count - 1), data, e);
81209         }
81210
81211         
81212         else {
81213             delete me.overRecord;
81214             delete me.currentPosition;
81215             me.getIndicator().setWidth(Ext.fly(view.el).getWidth()).showAt(0, 0);
81216             me.valid = true;
81217         }
81218         return me.dropAllowed;
81219     },
81220
81221     onContainerDrop : function(dd, e, data) {
81222         return this.onNodeDrop(dd, null, e, data);
81223     },
81224
81225     onNodeDrop: function(node, dragZone, e, data) {
81226         var me = this,
81227             dropped = false,
81228
81229             
81230             
81231             
81232             
81233             processDrop = function () {
81234                 me.invalidateDrop();
81235                 me.handleNodeDrop(data, me.overRecord, me.currentPosition);
81236                 dropped = true;
81237                 me.fireViewEvent('drop', node, data, me.overRecord, me.currentPosition);
81238             },
81239             performOperation = false;
81240
81241         if (me.valid) {
81242             performOperation = me.fireViewEvent('beforedrop', node, data, me.overRecord, me.currentPosition, processDrop);
81243             if (performOperation !== false) {
81244                 
81245                 if (!dropped) {
81246                     processDrop();
81247                 }
81248             }
81249         }
81250         return performOperation;
81251     },
81252     
81253     destroy: function(){
81254         Ext.destroy(this.indicator);
81255         delete this.indicator;
81256         this.callParent();
81257     }
81258 });
81259
81260 Ext.define('Ext.grid.ViewDropZone', {
81261     extend: 'Ext.view.DropZone',
81262
81263     indicatorHtml: '<div class="x-grid-drop-indicator-left"></div><div class="x-grid-drop-indicator-right"></div>',
81264     indicatorCls: 'x-grid-drop-indicator',
81265
81266     handleNodeDrop : function(data, record, position) {
81267         var view = this.view,
81268             store = view.getStore(),
81269             index, records, i, len;
81270
81271         
81272         if (data.copy) {
81273             records = data.records;
81274             data.records = [];
81275             for (i = 0, len = records.length; i < len; i++) {
81276                 data.records.push(records[i].copy(records[i].getId()));
81277             }
81278         } else {
81279             
81280             data.view.store.remove(data.records, data.view === view);
81281         }
81282
81283         index = store.indexOf(record);
81284
81285         
81286         if (position !== 'before') {
81287             index++;
81288         }
81289         store.insert(index, data.records);
81290         view.getSelectionModel().select(data.records);
81291     }
81292 });
81293
81294 Ext.define('Ext.grid.column.Action', {
81295     extend: 'Ext.grid.column.Column',
81296     alias: ['widget.actioncolumn'],
81297     alternateClassName: 'Ext.grid.ActionColumn',
81298
81299     
81300     
81301     
81302     
81303     
81304     
81305     
81306     
81307     
81308     
81309     header: '&#160;',
81310
81311     actionIdRe: new RegExp(Ext.baseCSSPrefix + 'action-col-(\\d+)'),
81312
81313     
81314     altText: '',
81315
81316     sortable: false,
81317
81318     constructor: function(config) {
81319         var me = this,
81320             cfg = Ext.apply({}, config),
81321             items = cfg.items || [me],
81322             l = items.length,
81323             i,
81324             item;
81325
81326         
81327         delete cfg.items;
81328         me.callParent([cfg]);
81329
81330         
81331         me.items = items;
81332
81333
81334
81335         me.renderer = function(v, meta) {
81336
81337             v = Ext.isFunction(cfg.renderer) ? cfg.renderer.apply(this, arguments)||'' : '';
81338
81339             meta.tdCls += ' ' + Ext.baseCSSPrefix + 'action-col-cell';
81340             for (i = 0; i < l; i++) {
81341                 item = items[i];
81342                 item.disable = Ext.Function.bind(me.disableAction, me, [i]);
81343                 item.enable = Ext.Function.bind(me.enableAction, me, [i]);
81344                 v += '<img alt="' + (item.altText || me.altText) + '" src="' + (item.icon || Ext.BLANK_IMAGE_URL) +
81345                     '" class="' + Ext.baseCSSPrefix + 'action-col-icon ' + Ext.baseCSSPrefix + 'action-col-' + String(i) + ' ' + (item.disabled ? Ext.baseCSSPrefix + 'item-disabled' : ' ') + (item.iconCls || '') +
81346                     ' ' + (Ext.isFunction(item.getClass) ? item.getClass.apply(item.scope||me.scope||me, arguments) : (me.iconCls || '')) + '"' +
81347                     ((item.tooltip) ? ' data-qtip="' + item.tooltip + '"' : '') + ' />';
81348             }
81349             return v;
81350         };
81351     },
81352
81353     
81354     enableAction: function(index) {
81355         var me = this;
81356
81357         if (!index) {
81358             index = 0;
81359         } else if (!Ext.isNumber(index)) {
81360             index = Ext.Array.indexOf(me.items, index);
81361         }
81362         me.items[index].disabled = false;
81363         me.up('tablepanel').el.select('.' + Ext.baseCSSPrefix + 'action-col-' + index).removeCls(me.disabledCls);
81364     },
81365
81366     
81367     disableAction: function(index) {
81368         var me = this;
81369
81370         if (!index) {
81371             index = 0;
81372         } else if (!Ext.isNumber(index)) {
81373             index = Ext.Array.indexOf(me.items, index);
81374         }
81375         me.items[index].disabled = true;
81376         me.up('tablepanel').el.select('.' + Ext.baseCSSPrefix + 'action-col-' + index).addCls(me.disabledCls);
81377     },
81378
81379     destroy: function() {
81380         delete this.items;
81381         delete this.renderer;
81382         return this.callParent(arguments);
81383     },
81384
81385     
81386     processEvent : function(type, view, cell, recordIndex, cellIndex, e){
81387         var me = this,
81388             match = e.getTarget().className.match(me.actionIdRe),
81389             item, fn;
81390             
81391         if (match) {
81392             item = me.items[parseInt(match[1], 10)];
81393             if (item) {
81394                 if (type == 'click') {
81395                     fn = item.handler || me.handler;
81396                     if (fn && !item.disabled) {
81397                         fn.call(item.scope || me.scope || me, view, recordIndex, cellIndex, item, e);
81398                     }
81399                 } else if (type == 'mousedown' && item.stopSelection !== false) {
81400                     return false;
81401                 }
81402             }
81403         }
81404         return me.callParent(arguments);
81405     },
81406
81407     cascade: function(fn, scope) {
81408         fn.call(scope||this, this);
81409     },
81410
81411     
81412     getRefItems: function() {
81413         return [];
81414     }
81415 });
81416
81417 Ext.define('Ext.grid.column.Boolean', {
81418     extend: 'Ext.grid.column.Column',
81419     alias: ['widget.booleancolumn'],
81420     alternateClassName: 'Ext.grid.BooleanColumn',
81421
81422     
81423     trueText: 'true',
81424
81425     
81426     falseText: 'false',
81427
81428     
81429     undefinedText: '&#160;',
81430
81431     constructor: function(cfg){
81432         this.callParent(arguments);
81433         var trueText      = this.trueText,
81434             falseText     = this.falseText,
81435             undefinedText = this.undefinedText;
81436
81437         this.renderer = function(value){
81438             if(value === undefined){
81439                 return undefinedText;
81440             }
81441             if(!value || value === 'false'){
81442                 return falseText;
81443             }
81444             return trueText;
81445         };
81446     }
81447 });
81448
81449 Ext.define('Ext.grid.column.Date', {
81450     extend: 'Ext.grid.column.Column',
81451     alias: ['widget.datecolumn'],
81452     requires: ['Ext.Date'],
81453     alternateClassName: 'Ext.grid.DateColumn',
81454
81455     
81456
81457     initComponent: function(){
81458         var me = this;
81459         
81460         me.callParent(arguments);
81461         if (!me.format) {
81462             me.format = Ext.Date.defaultFormat;
81463         }
81464         me.renderer = Ext.util.Format.dateRenderer(me.format);
81465     }
81466 });
81467
81468 Ext.define('Ext.grid.column.Number', {
81469     extend: 'Ext.grid.column.Column',
81470     alias: ['widget.numbercolumn'],
81471     requires: ['Ext.util.Format'],
81472     alternateClassName: 'Ext.grid.NumberColumn',
81473
81474     
81475     format : '0,000.00',
81476
81477     constructor: function(cfg) {
81478         this.callParent(arguments);
81479         this.renderer = Ext.util.Format.numberRenderer(this.format);
81480     }
81481 });
81482
81483 Ext.define('Ext.grid.column.Template', {
81484     extend: 'Ext.grid.column.Column',
81485     alias: ['widget.templatecolumn'],
81486     requires: ['Ext.XTemplate'],
81487     alternateClassName: 'Ext.grid.TemplateColumn',
81488
81489     
81490
81491     constructor: function(cfg){
81492         var me = this,
81493             tpl;
81494             
81495         me.callParent(arguments);
81496         tpl = me.tpl = (!Ext.isPrimitive(me.tpl) && me.tpl.compile) ? me.tpl : Ext.create('Ext.XTemplate', me.tpl);
81497
81498         me.renderer = function(value, p, record) {
81499             var data = Ext.apply({}, record.data, record.getAssociatedData());
81500             return tpl.apply(data);
81501         };
81502     }
81503 });
81504
81505
81506 Ext.define('Ext.grid.feature.Feature', {
81507     extend: 'Ext.util.Observable',
81508     alias: 'feature.feature',
81509     
81510     isFeature: true,
81511     disabled: false,
81512     
81513     
81514     hasFeatureEvent: true,
81515     
81516     
81517     eventPrefix: null,
81518     
81519     
81520     eventSelector: null,
81521     
81522     
81523     view: null,
81524     
81525     
81526     grid: null,
81527     
81528     
81529     collectData: false,
81530         
81531     getFeatureTpl: function() {
81532         return '';
81533     },
81534     
81535     
81536     getFireEventArgs: function(eventName, view, featureTarget, e) {
81537         return [eventName, view, featureTarget, e];
81538     },
81539     
81540     
81541     attachEvents: function() {
81542         
81543     },
81544     
81545     getFragmentTpl: function() {
81546         return;
81547     },
81548     
81549     
81550     mutateMetaRowTpl: function(metaRowTplArray) {
81551         
81552     },
81553     
81554     
81555     getMetaRowTplFragments: function() {
81556         return {};
81557     },
81558
81559     getTableFragments: function() {
81560         return {};
81561     },
81562     
81563     
81564     getAdditionalData: function(data, idx, record, orig) {
81565         return {};
81566     },
81567     
81568     
81569     enable: function() {
81570         this.disabled = false;
81571     },
81572     
81573     
81574     disable: function() {
81575         this.disabled = true;
81576     }
81577     
81578 });
81579
81580 Ext.define('Ext.grid.feature.AbstractSummary', {
81581     
81582     
81583    
81584     extend: 'Ext.grid.feature.Feature',
81585     
81586     alias: 'feature.abstractsummary',
81587    
81588     
81589    
81590    
81591     showSummaryRow: true,
81592     
81593     
81594     nestedIdRe: /\{\{id\}([\w\-]*)\}/g,
81595     
81596     
81597     toggleSummaryRow: function(visible){
81598         this.showSummaryRow = !!visible;
81599     },
81600     
81601     
81602     getSummaryFragments: function(){
81603         var fragments = {};
81604         if (this.showSummaryRow) {
81605             Ext.apply(fragments, {
81606                 printSummaryRow: Ext.bind(this.printSummaryRow, this)
81607             });
81608         }
81609         return fragments;
81610     },
81611     
81612     
81613     printSummaryRow: function(index){
81614         var inner = this.view.getTableChunker().metaRowTpl.join(''),
81615             prefix = Ext.baseCSSPrefix;
81616         
81617         inner = inner.replace(prefix + 'grid-row', prefix + 'grid-row-summary');
81618         inner = inner.replace('{{id}}', '{gridSummaryValue}');
81619         inner = inner.replace(this.nestedIdRe, '{id$1}');  
81620         inner = inner.replace('{[this.embedRowCls()]}', '{rowCls}');
81621         inner = inner.replace('{[this.embedRowAttr()]}', '{rowAttr}');
81622         inner = Ext.create('Ext.XTemplate', inner, {
81623             firstOrLastCls: Ext.view.TableChunker.firstOrLastCls
81624         });
81625         
81626         return inner.applyTemplate({
81627             columns: this.getPrintData(index)
81628         });
81629     },
81630     
81631     
81632     getColumnValue: function(column, summaryData){
81633         var comp     = Ext.getCmp(column.id),
81634             value    = summaryData[column.id],
81635             renderer = comp.summaryRenderer;
81636
81637         if (renderer) {
81638             value = renderer.call(
81639                 comp.scope || this,
81640                 value,
81641                 summaryData,
81642                 column.dataIndex
81643             );
81644         }
81645         return value;
81646     },
81647     
81648     
81649     getSummary: function(store, type, field, group){
81650         if (type) {
81651             if (Ext.isFunction(type)) {
81652                 return store.aggregate(type, null, group);
81653             }
81654             
81655             switch (type) {
81656                 case 'count':
81657                     return store.count(group);
81658                 case 'min':
81659                     return store.min(field, group);
81660                 case 'max':
81661                     return store.max(field, group);
81662                 case 'sum':
81663                     return store.sum(field, group);
81664                 case 'average':
81665                     return store.average(field, group);
81666                 default:
81667                     return group ? {} : '';
81668                     
81669             }
81670         }
81671     }
81672     
81673 });
81674
81675
81676 Ext.define('Ext.grid.feature.Chunking', {
81677     extend: 'Ext.grid.feature.Feature',
81678     alias: 'feature.chunking',
81679     
81680     chunkSize: 20,
81681     rowHeight: Ext.isIE ? 27 : 26,
81682     visibleChunk: 0,
81683     hasFeatureEvent: false,
81684     attachEvents: function() {
81685         var grid = this.view.up('gridpanel'),
81686             scroller = grid.down('gridscroller[dock=right]');
81687         scroller.el.on('scroll', this.onBodyScroll, this, {buffer: 300});
81688         
81689     },
81690     
81691     onBodyScroll: function(e, t) {
81692         var view = this.view,
81693             top  = t.scrollTop,
81694             nextChunk = Math.floor(top / this.rowHeight / this.chunkSize);
81695         if (nextChunk !== this.visibleChunk) {
81696         
81697             this.visibleChunk = nextChunk;
81698             view.refresh();
81699             view.el.dom.scrollTop = top;
81700             
81701             view.el.dom.scrollTop = top;
81702         }
81703     },
81704     
81705     collectData: function(records, preppedRecords, startIndex, fullWidth, orig) {
81706         var o = {
81707             fullWidth: orig.fullWidth,
81708             chunks: []
81709         },
81710         
81711         
81712         recordCount = orig.rows.length,
81713         start = 0,
81714         i = 0,
81715         visibleChunk = this.visibleChunk,
81716         chunk,
81717         rows,
81718         chunkLength;
81719
81720         for (; start < recordCount; start+=this.chunkSize, i++) {
81721             if (start+this.chunkSize > recordCount) {
81722                 chunkLength = recordCount - start;
81723             } else {
81724                 chunkLength = this.chunkSize;
81725             }
81726             
81727             if (i >= visibleChunk - 1 && i <= visibleChunk + 1) {
81728                 rows = orig.rows.slice(start, start+this.chunkSize);
81729             } else {
81730                 rows = [];
81731             }
81732             o.chunks.push({
81733                 rows: rows,
81734                 fullWidth: fullWidth,
81735                 chunkHeight: chunkLength * this.rowHeight
81736             });
81737         }
81738         
81739         
81740         return o;
81741     },
81742     
81743     getTableFragments: function() {
81744         return {
81745             openTableWrap: function() {
81746                 return '<tpl for="chunks"><div class="' + Ext.baseCSSPrefix + 'grid-chunk" style="height: {chunkHeight}px;">';
81747             },
81748             closeTableWrap: function() {
81749                 return '</div></tpl>';
81750             }
81751         };
81752     }
81753 });
81754
81755
81756 Ext.define('Ext.grid.feature.Grouping', {
81757     extend: 'Ext.grid.feature.Feature',
81758     alias: 'feature.grouping',
81759
81760     eventPrefix: 'group',
81761     eventSelector: '.' + Ext.baseCSSPrefix + 'grid-group-hd',
81762
81763     constructor: function() {
81764         var me = this;
81765         
81766         me.collapsedState = {};
81767         me.callParent(arguments);
81768     },
81769     
81770     
81771
81772     
81773
81774     
81775
81776     
81777
81778     
81779
81780     
81781     groupHeaderTpl: 'Group: {name}',
81782
81783     
81784     depthToIndent: 17,
81785
81786     collapsedCls: Ext.baseCSSPrefix + 'grid-group-collapsed',
81787     hdCollapsedCls: Ext.baseCSSPrefix + 'grid-group-hd-collapsed',
81788
81789     
81790     groupByText : 'Group By This Field',
81791     
81792     showGroupsText : 'Show in Groups',
81793
81794     
81795     hideGroupedHeader : false,
81796
81797     
81798     startCollapsed : false,
81799
81800     
81801     enableGroupingMenu : true,
81802
81803     
81804     enableNoGroups : true,
81805     
81806     enable: function() {
81807         var me    = this,
81808             view  = me.view,
81809             store = view.store,
81810             groupToggleMenuItem;
81811             
81812         me.lastGroupField = me.getGroupField();
81813
81814         if (me.lastGroupIndex) {
81815             store.group(me.lastGroupIndex);
81816         }
81817         me.callParent();
81818         groupToggleMenuItem = me.view.headerCt.getMenu().down('#groupToggleMenuItem');
81819         groupToggleMenuItem.setChecked(true, true);
81820         me.refreshIf();
81821     },
81822
81823     disable: function() {
81824         var me    = this,
81825             view  = me.view,
81826             store = view.store,
81827             remote = store.remoteGroup,
81828             groupToggleMenuItem,
81829             lastGroup;
81830             
81831         lastGroup = store.groupers.first();
81832         if (lastGroup) {
81833             me.lastGroupIndex = lastGroup.property;
81834             me.block();
81835             store.clearGrouping();
81836             me.unblock();
81837         }
81838         
81839         me.callParent();
81840         groupToggleMenuItem = me.view.headerCt.getMenu().down('#groupToggleMenuItem');
81841         groupToggleMenuItem.setChecked(true, true);
81842         groupToggleMenuItem.setChecked(false, true);
81843         if (!remote) {
81844             view.refresh();
81845         }
81846     },
81847     
81848     refreshIf: function() {
81849         if (this.blockRefresh !== true) {
81850             this.view.refresh();
81851         }    
81852     },
81853
81854     getFeatureTpl: function(values, parent, x, xcount) {
81855         var me = this;
81856         
81857         return [
81858             '<tpl if="typeof rows !== \'undefined\'">',
81859                 
81860                 '<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>',
81861                 
81862                 '<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>',
81863             '</tpl>'
81864         ].join('');
81865     },
81866
81867     getFragmentTpl: function() {
81868         return {
81869             indentByDepth: this.indentByDepth,
81870             depthToIndent: this.depthToIndent
81871         };
81872     },
81873
81874     indentByDepth: function(values) {
81875         var depth = values.depth || 0;
81876         return 'style="padding-left:'+ depth * this.depthToIndent + 'px;"';
81877     },
81878
81879     
81880     
81881     destroy: function() {
81882         var me = this;
81883         
81884         delete me.view;
81885         delete me.prunedHeader;
81886     },
81887
81888     
81889     attachEvents: function() {
81890         var me = this,
81891             view = me.view;
81892
81893         view.on({
81894             scope: me,
81895             groupclick: me.onGroupClick,
81896             rowfocus: me.onRowFocus
81897         });
81898         view.store.on('groupchange', me.onGroupChange, me);
81899
81900         me.pruneGroupedHeader();
81901
81902         if (me.enableGroupingMenu) {
81903             me.injectGroupingMenu();
81904         }
81905         me.lastGroupField = me.getGroupField();
81906         me.block();
81907         me.onGroupChange();
81908         me.unblock();
81909     },
81910     
81911     injectGroupingMenu: function() {
81912         var me       = this,
81913             view     = me.view,
81914             headerCt = view.headerCt;
81915         headerCt.showMenuBy = me.showMenuBy;
81916         headerCt.getMenuItems = me.getMenuItems();
81917     },
81918     
81919     showMenuBy: function(t, header) {
81920         var menu = this.getMenu(),
81921             groupMenuItem  = menu.down('#groupMenuItem'),
81922             groupableMth = header.groupable === false ?  'disable' : 'enable';
81923             
81924         groupMenuItem[groupableMth]();
81925         Ext.grid.header.Container.prototype.showMenuBy.apply(this, arguments);
81926     },
81927     
81928     getMenuItems: function() {
81929         var me                 = this,
81930             groupByText        = me.groupByText,
81931             disabled           = me.disabled,
81932             showGroupsText     = me.showGroupsText,
81933             enableNoGroups     = me.enableNoGroups,
81934             groupMenuItemClick = Ext.Function.bind(me.onGroupMenuItemClick, me),
81935             groupToggleMenuItemClick = Ext.Function.bind(me.onGroupToggleMenuItemClick, me);
81936         
81937         
81938         return function() {
81939             var o = Ext.grid.header.Container.prototype.getMenuItems.call(this);
81940             o.push('-', {
81941                 iconCls: Ext.baseCSSPrefix + 'group-by-icon',
81942                 itemId: 'groupMenuItem',
81943                 text: groupByText,
81944                 handler: groupMenuItemClick
81945             });
81946             if (enableNoGroups) {
81947                 o.push({
81948                     itemId: 'groupToggleMenuItem',
81949                     text: showGroupsText,
81950                     checked: !disabled,
81951                     checkHandler: groupToggleMenuItemClick
81952                 });
81953             }
81954             return o;
81955         };
81956     },
81957
81958
81959     
81960     onGroupMenuItemClick: function(menuItem, e) {
81961         var me = this,
81962             menu = menuItem.parentMenu,
81963             hdr  = menu.activeHeader,
81964             view = me.view,
81965             store = view.store,
81966             remote = store.remoteGroup;
81967
81968         delete me.lastGroupIndex;
81969         me.block();
81970         me.enable();
81971         store.group(hdr.dataIndex);
81972         me.pruneGroupedHeader();
81973         me.unblock();
81974         if (!remote) {
81975             view.refresh();
81976         }  
81977     },
81978     
81979     block: function(){
81980         this.blockRefresh = this.view.blockRefresh = true;
81981     },
81982     
81983     unblock: function(){
81984         this.blockRefresh = this.view.blockRefresh = false;
81985     },
81986
81987     
81988     onGroupToggleMenuItemClick: function(menuItem, checked) {
81989         this[checked ? 'enable' : 'disable']();
81990     },
81991
81992     
81993     pruneGroupedHeader: function() {
81994         var me         = this,
81995             view       = me.view,
81996             store      = view.store,
81997             groupField = me.getGroupField(),
81998             headerCt   = view.headerCt,
81999             header     = headerCt.down('header[dataIndex=' + groupField + ']');
82000
82001         if (header) {
82002             if (me.prunedHeader) {
82003                 me.prunedHeader.show();
82004             }
82005             me.prunedHeader = header;
82006             header.hide();
82007         }
82008     },
82009
82010     getGroupField: function(){
82011         var group = this.view.store.groupers.first();
82012         if (group) {
82013             return group.property;    
82014         }
82015         return ''; 
82016     },
82017
82018     
82019     onRowFocus: function(rowIdx) {
82020         var node    = this.view.getNode(rowIdx),
82021             groupBd = Ext.fly(node).up('.' + this.collapsedCls);
82022
82023         if (groupBd) {
82024             
82025             
82026             this.expand(groupBd);
82027         }
82028     },
82029
82030     
82031     expand: function(groupBd) {
82032         var me = this,
82033             view = me.view,
82034             grid = view.up('gridpanel'),
82035             groupBdDom = Ext.getDom(groupBd);
82036             
82037         me.collapsedState[groupBdDom.id] = false;
82038
82039         groupBd.removeCls(me.collapsedCls);
82040         groupBd.prev().removeCls(me.hdCollapsedCls);
82041
82042         grid.determineScrollbars();
82043         grid.invalidateScroller();
82044         view.fireEvent('groupexpand');
82045     },
82046
82047     
82048     collapse: function(groupBd) {
82049         var me = this,
82050             view = me.view,
82051             grid = view.up('gridpanel'),
82052             groupBdDom = Ext.getDom(groupBd);
82053             
82054         me.collapsedState[groupBdDom.id] = true;
82055
82056         groupBd.addCls(me.collapsedCls);
82057         groupBd.prev().addCls(me.hdCollapsedCls);
82058
82059         grid.determineScrollbars();
82060         grid.invalidateScroller();
82061         view.fireEvent('groupcollapse');
82062     },
82063     
82064     onGroupChange: function(){
82065         var me = this,
82066             field = me.getGroupField(),
82067             menuItem;
82068             
82069         if (me.hideGroupedHeader) {
82070             if (me.lastGroupField) {
82071                 menuItem = me.getMenuItem(me.lastGroupField);
82072                 if (menuItem) {
82073                     menuItem.setChecked(true);
82074                 }
82075             }
82076             if (field) {
82077                 menuItem = me.getMenuItem(field);
82078                 if (menuItem) {
82079                     menuItem.setChecked(false);
82080                 }
82081             }
82082         }
82083         if (me.blockRefresh !== true) {
82084             me.view.refresh();
82085         }
82086         me.lastGroupField = field;
82087     },
82088     
82089     
82090     getMenuItem: function(dataIndex){
82091         var view = this.view,
82092             header = view.headerCt.down('gridcolumn[dataIndex=' + dataIndex + ']'),
82093             menu = view.headerCt.getMenu();
82094             
82095         return menu.down('menuitem[headerId='+ header.id +']');
82096     },
82097
82098     
82099     onGroupClick: function(view, group, idx, foo, e) {
82100         var me = this,
82101             toggleCls = me.toggleCls,
82102             groupBd = Ext.fly(group.nextSibling, '_grouping');
82103
82104         if (groupBd.hasCls(me.collapsedCls)) {
82105             me.expand(groupBd);
82106         } else {
82107             me.collapse(groupBd);
82108         }
82109     },
82110
82111     
82112     getMetaRowTplFragments: function() {
82113         return {
82114             isRow: this.isRow,
82115             closeRow: this.closeRow
82116         };
82117     },
82118
82119     
82120     
82121     isRow: function() {
82122         return '<tpl if="typeof rows === \'undefined\'">';
82123     },
82124
82125     
82126     
82127     closeRow: function() {
82128         return '</tpl>';
82129     },
82130
82131     
82132     mutateMetaRowTpl: function(metaRowTpl) {
82133         metaRowTpl.unshift('{[this.isRow()]}');
82134         metaRowTpl.push('{[this.closeRow()]}');
82135     },
82136
82137     
82138     
82139     getAdditionalData: function(data, idx, record, orig) {
82140         var view = this.view,
82141             hCt  = view.headerCt,
82142             col  = hCt.items.getAt(0),
82143             o = {},
82144             tdAttrKey = col.id + '-tdAttr';
82145
82146         
82147         o[tdAttrKey] = this.indentByDepth(data) + " " + (orig[tdAttrKey] ? orig[tdAttrKey] : '');
82148         o.collapsed = 'true';
82149         return o;
82150     },
82151
82152     
82153     getGroupRows: function(group, records, preppedRecords, fullWidth) {
82154         var me = this,
82155             children = group.children,
82156             rows = group.rows = [],
82157             view = me.view;
82158         group.viewId = view.id;
82159
82160         Ext.Array.each(records, function(record, idx) {
82161             if (Ext.Array.indexOf(children, record) != -1) {
82162                 rows.push(Ext.apply(preppedRecords[idx], {
82163                     depth: 1
82164                 }));
82165             }
82166         });
82167         delete group.children;
82168         group.fullWidth = fullWidth;
82169         if (me.collapsedState[view.id + '-gp-' + group.name]) {
82170             group.collapsedCls = me.collapsedCls;
82171             group.hdCollapsedCls = me.hdCollapsedCls;
82172         }
82173
82174         return group;
82175     },
82176
82177     
82178     collectData: function(records, preppedRecords, startIndex, fullWidth, o) {
82179         var me    = this,
82180             store = me.view.store,
82181             groups;
82182             
82183         if (!me.disabled && store.isGrouped()) {
82184             groups = store.getGroups();
82185             Ext.Array.each(groups, function(group, idx){
82186                 me.getGroupRows(group, records, preppedRecords, fullWidth);
82187             }, me);
82188             return {
82189                 rows: groups,
82190                 fullWidth: fullWidth
82191             };
82192         }
82193         return o;
82194     },
82195     
82196     
82197     
82198     
82199     
82200     getFireEventArgs: function(type, view, featureTarget, e) {
82201         var returnArray = [type, view, featureTarget],
82202             groupBd     = Ext.fly(featureTarget.nextSibling, '_grouping'),
82203             groupBdId   = Ext.getDom(groupBd).id,
82204             prefix      = view.id + '-gp-',
82205             groupName   = groupBdId.substr(prefix.length);
82206         
82207         returnArray.push(groupName, e);
82208         
82209         return returnArray;
82210     }
82211 });
82212
82213
82214 Ext.define('Ext.grid.feature.GroupingSummary', {
82215
82216     
82217
82218     extend: 'Ext.grid.feature.Grouping',
82219
82220     alias: 'feature.groupingsummary',
82221
82222     mixins: {
82223         summary: 'Ext.grid.feature.AbstractSummary'
82224     },
82225
82226     
82227
82228
82229    
82230    getFeatureTpl: function() {
82231         var tpl = this.callParent(arguments);
82232
82233         if (this.showSummaryRow) {
82234             
82235             tpl = tpl.replace('</tpl>', '');
82236             tpl += '{[this.printSummaryRow(xindex)]}</tpl>';
82237         }
82238         return tpl;
82239     },
82240
82241     
82242     getFragmentTpl: function() {
82243         var me = this,
82244             fragments = me.callParent();
82245
82246         Ext.apply(fragments, me.getSummaryFragments());
82247         if (me.showSummaryRow) {
82248             
82249             me.summaryGroups = me.view.store.getGroups();
82250             me.summaryData = me.generateSummaryData();
82251         }
82252         return fragments;
82253     },
82254
82255     
82256     getPrintData: function(index){
82257         var me = this,
82258             columns = me.view.headerCt.getColumnsForTpl(),
82259             i = 0,
82260             length = columns.length,
82261             data = [],
82262             name = me.summaryGroups[index - 1].name,
82263             active = me.summaryData[name],
82264             column;
82265
82266         for (; i < length; ++i) {
82267             column = columns[i];
82268             column.gridSummaryValue = this.getColumnValue(column, active);
82269             data.push(column);
82270         }
82271         return data;
82272     },
82273
82274     
82275     generateSummaryData: function(){
82276         var me = this,
82277             data = {},
82278             remoteData = {},
82279             store = me.view.store,
82280             groupField = this.getGroupField(),
82281             reader = store.proxy.reader,
82282             groups = me.summaryGroups,
82283             columns = me.view.headerCt.getColumnsForTpl(),
82284             remote,
82285             i,
82286             length,
82287             fieldData,
82288             root,
82289             key,
82290             comp;
82291
82292         for (i = 0, length = groups.length; i < length; ++i) {
82293             data[groups[i].name] = {};
82294         }
82295
82296         
82297         if (me.remoteRoot && reader.rawData) {
82298             
82299             root = reader.root;
82300             reader.root = me.remoteRoot;
82301             reader.buildExtractors(true);
82302             Ext.Array.each(reader.getRoot(reader.rawData), function(value) {
82303                  remoteData[value[groupField]] = value;
82304             });
82305             
82306             reader.root = root;
82307             reader.buildExtractors(true);
82308         }
82309
82310         for (i = 0, length = columns.length; i < length; ++i) {
82311             comp = Ext.getCmp(columns[i].id);
82312             fieldData = me.getSummary(store, comp.summaryType, comp.dataIndex, true);
82313
82314             for (key in fieldData) {
82315                 if (fieldData.hasOwnProperty(key)) {
82316                     data[key][comp.id] = fieldData[key];
82317                 }
82318             }
82319
82320             for (key in remoteData) {
82321                 if (remoteData.hasOwnProperty(key)) {
82322                     remote = remoteData[key][comp.dataIndex];
82323                     if (remote !== undefined && data[key] !== undefined) {
82324                         data[key][comp.id] = remote;
82325                     }
82326                 }
82327             }
82328         }
82329         return data;
82330     }
82331 });
82332
82333
82334 Ext.define('Ext.grid.feature.RowBody', {
82335     extend: 'Ext.grid.feature.Feature',
82336     alias: 'feature.rowbody',
82337     rowBodyHiddenCls: Ext.baseCSSPrefix + 'grid-row-body-hidden',
82338     rowBodyTrCls: Ext.baseCSSPrefix + 'grid-rowbody-tr',
82339     rowBodyTdCls: Ext.baseCSSPrefix + 'grid-cell-rowbody',
82340     rowBodyDivCls: Ext.baseCSSPrefix + 'grid-rowbody',
82341
82342     eventPrefix: 'rowbody',
82343     eventSelector: '.' + Ext.baseCSSPrefix + 'grid-rowbody-tr',
82344     
82345     getRowBody: function(values) {
82346         return [
82347             '<tr class="' + this.rowBodyTrCls + ' {rowBodyCls}">',
82348                 '<td class="' + this.rowBodyTdCls + '" colspan="{rowBodyColspan}">',
82349                     '<div class="' + this.rowBodyDivCls + '">{rowBody}</div>',
82350                 '</td>',
82351             '</tr>'
82352         ].join('');
82353     },
82354     
82355     
82356     getMetaRowTplFragments: function() {
82357         return {
82358             getRowBody: this.getRowBody,
82359             rowBodyTrCls: this.rowBodyTrCls,
82360             rowBodyTdCls: this.rowBodyTdCls,
82361             rowBodyDivCls: this.rowBodyDivCls
82362         };
82363     },
82364
82365     mutateMetaRowTpl: function(metaRowTpl) {
82366         metaRowTpl.push('{[this.getRowBody(values)]}');
82367     },
82368
82369     
82370     getAdditionalData: function(data, idx, record, orig) {
82371         var headerCt = this.view.headerCt,
82372             colspan  = headerCt.getColumnCount();
82373
82374         return {
82375             rowBody: "",
82376             rowBodyCls: this.rowBodyCls,
82377             rowBodyColspan: colspan
82378         };
82379     }
82380 });
82381
82382 Ext.define('Ext.grid.feature.RowWrap', {
82383     extend: 'Ext.grid.feature.Feature',
82384     alias: 'feature.rowwrap',
82385
82386     
82387     hasFeatureEvent: false,
82388     
82389     mutateMetaRowTpl: function(metaRowTpl) {        
82390         
82391         
82392         metaRowTpl[0] = metaRowTpl[0].replace(Ext.baseCSSPrefix + 'grid-row', '');
82393         metaRowTpl[0] = metaRowTpl[0].replace("{[this.embedRowCls()]}", "");
82394         
82395         metaRowTpl.unshift('<table class="' + Ext.baseCSSPrefix + 'grid-table ' + Ext.baseCSSPrefix + 'grid-table-resizer" style="width: {[this.embedFullWidth()]}px;">');
82396         
82397         metaRowTpl.unshift('<tr class="' + Ext.baseCSSPrefix + 'grid-row {[this.embedRowCls()]}"><td colspan="{[this.embedColSpan()]}"><div class="' + Ext.baseCSSPrefix + 'grid-rowwrap-div">');
82398         
82399         
82400         metaRowTpl.push('</table>');
82401         
82402         metaRowTpl.push('</div></td></tr>');
82403     },
82404     
82405     embedColSpan: function() {
82406         return '{colspan}';
82407     },
82408     
82409     embedFullWidth: function() {
82410         return '{fullWidth}';
82411     },
82412     
82413     getAdditionalData: function(data, idx, record, orig) {
82414         var headerCt = this.view.headerCt,
82415             colspan  = headerCt.getColumnCount(),
82416             fullWidth = headerCt.getFullWidth(),
82417             items    = headerCt.query('gridcolumn'),
82418             itemsLn  = items.length,
82419             i = 0,
82420             o = {
82421                 colspan: colspan,
82422                 fullWidth: fullWidth
82423             },
82424             id,
82425             tdClsKey,
82426             colResizerCls;
82427
82428         for (; i < itemsLn; i++) {
82429             id = items[i].id;
82430             tdClsKey = id + '-tdCls';
82431             colResizerCls = Ext.baseCSSPrefix + 'grid-col-resizer-'+id;
82432             
82433             
82434             
82435             o[tdClsKey] = colResizerCls + " " + (orig[tdClsKey] ? orig[tdClsKey] : '');
82436             
82437             o[id+'-tdAttr'] = " style=\"width: " + (items[i].hidden ? 0 : items[i].getDesiredWidth()) + "px;\" ";
82438             if (orig[id+'-tdAttr']) {
82439                 o[id+'-tdAttr'] += orig[id+'-tdAttr'];
82440             }
82441             
82442         }
82443
82444         return o;
82445     },
82446     
82447     getMetaRowTplFragments: function() {
82448         return {
82449             embedFullWidth: this.embedFullWidth,
82450             embedColSpan: this.embedColSpan
82451         };
82452     }
82453     
82454 });
82455
82456 Ext.define('Ext.grid.feature.Summary', {
82457     
82458     
82459     
82460     extend: 'Ext.grid.feature.AbstractSummary',
82461     
82462     alias: 'feature.summary',
82463     
82464     
82465     
82466     
82467     getFragmentTpl: function() {
82468         
82469         this.summaryData = this.generateSummaryData(); 
82470         return this.getSummaryFragments();
82471     },
82472     
82473     
82474     getTableFragments: function(){
82475         if (this.showSummaryRow) {
82476             return {
82477                 closeRows: this.closeRows
82478             };
82479         }
82480     },
82481     
82482     
82483     closeRows: function() {
82484         return '</tpl>{[this.printSummaryRow()]}';
82485     },
82486     
82487     
82488     getPrintData: function(index){
82489         var me = this,
82490             columns = me.view.headerCt.getColumnsForTpl(),
82491             i = 0,
82492             length = columns.length,
82493             data = [],
82494             active = me.summaryData,
82495             column;
82496             
82497         for (; i < length; ++i) {
82498             column = columns[i];
82499             column.gridSummaryValue = this.getColumnValue(column, active);
82500             data.push(column);
82501         }
82502         return data;
82503     },
82504     
82505     
82506     generateSummaryData: function(){
82507         var me = this,
82508             data = {},
82509             store = me.view.store,
82510             columns = me.view.headerCt.getColumnsForTpl(),
82511             i = 0,
82512             length = columns.length,
82513             fieldData,
82514             key,
82515             comp;
82516             
82517         for (i = 0, length = columns.length; i < length; ++i) {
82518             comp = Ext.getCmp(columns[i].id);
82519             data[comp.id] = me.getSummary(store, comp.summaryType, comp.dataIndex, false);
82520         }
82521         return data;
82522     }
82523 });
82524
82525 Ext.define('Ext.grid.header.DragZone', {
82526     extend: 'Ext.dd.DragZone',
82527     colHeaderCls: Ext.baseCSSPrefix + 'column-header',
82528     maxProxyWidth: 120,
82529
82530     constructor: function(headerCt) {
82531         this.headerCt = headerCt;
82532         this.ddGroup =  this.getDDGroup();
82533         this.callParent([headerCt.el]);
82534         this.proxy.el.addCls(Ext.baseCSSPrefix + 'grid-col-dd');
82535     },
82536
82537     getDDGroup: function() {
82538         return 'header-dd-zone-' + this.headerCt.up('[scrollerOwner]').id;
82539     },
82540
82541     getDragData: function(e) {
82542         var header = e.getTarget('.'+this.colHeaderCls),
82543             headerCmp;
82544
82545         if (header) {
82546             headerCmp = Ext.getCmp(header.id);
82547             if (!this.headerCt.dragging && headerCmp.draggable && !(headerCmp.isOnLeftEdge(e) || headerCmp.isOnRightEdge(e))) {
82548                 var ddel = document.createElement('div');
82549                 ddel.innerHTML = Ext.getCmp(header.id).text;
82550                 return {
82551                     ddel: ddel,
82552                     header: headerCmp
82553                 };
82554             }
82555         }
82556         return false;
82557     },
82558
82559     onBeforeDrag: function() {
82560         return !(this.headerCt.dragging || this.disabled);
82561     },
82562
82563     onInitDrag: function() {
82564         this.headerCt.dragging = true;
82565         this.callParent(arguments);
82566     },
82567
82568     onDragDrop: function() {
82569         this.headerCt.dragging = false;
82570         this.callParent(arguments);
82571     },
82572
82573     afterRepair: function() {
82574         this.callParent();
82575         this.headerCt.dragging = false;
82576     },
82577
82578     getRepairXY: function() {
82579         return this.dragData.header.el.getXY();
82580     },
82581     
82582     disable: function() {
82583         this.disabled = true;
82584     },
82585     
82586     enable: function() {
82587         this.disabled = false;
82588     }
82589 });
82590
82591
82592 Ext.define('Ext.grid.header.DropZone', {
82593     extend: 'Ext.dd.DropZone',
82594     colHeaderCls: Ext.baseCSSPrefix + 'column-header',
82595     proxyOffsets: [-4, -9],
82596
82597     constructor: function(headerCt){
82598         this.headerCt = headerCt;
82599         this.ddGroup = this.getDDGroup();
82600         this.callParent([headerCt.el]);
82601     },
82602
82603     getDDGroup: function() {
82604         return 'header-dd-zone-' + this.headerCt.up('[scrollerOwner]').id;
82605     },
82606
82607     getTargetFromEvent : function(e){
82608         return e.getTarget('.' + this.colHeaderCls);
82609     },
82610
82611     getTopIndicator: function() {
82612         if (!this.topIndicator) {
82613             this.topIndicator = Ext.DomHelper.append(Ext.getBody(), {
82614                 cls: "col-move-top",
82615                 html: "&#160;"
82616             }, true);
82617         }
82618         return this.topIndicator;
82619     },
82620
82621     getBottomIndicator: function() {
82622         if (!this.bottomIndicator) {
82623             this.bottomIndicator = Ext.DomHelper.append(Ext.getBody(), {
82624                 cls: "col-move-bottom",
82625                 html: "&#160;"
82626             }, true);
82627         }
82628         return this.bottomIndicator;
82629     },
82630
82631     getLocation: function(e, t) {
82632         var x      = e.getXY()[0],
82633             region = Ext.fly(t).getRegion(),
82634             pos, header;
82635
82636         if ((region.right - x) <= (region.right - region.left) / 2) {
82637             pos = "after";
82638         } else {
82639             pos = "before";
82640         }
82641         return {
82642             pos: pos,
82643             header: Ext.getCmp(t.id),
82644             node: t
82645         };
82646     },
82647
82648     positionIndicator: function(draggedHeader, node, e){
82649         var location = this.getLocation(e, node),
82650             header = location.header,
82651             pos    = location.pos,
82652             nextHd = draggedHeader.nextSibling('gridcolumn:not([hidden])'),
82653             prevHd = draggedHeader.previousSibling('gridcolumn:not([hidden])'),
82654             region, topIndicator, bottomIndicator, topAnchor, bottomAnchor,
82655             topXY, bottomXY, headerCtEl, minX, maxX;
82656
82657         
82658         if (!header.draggable && header.getIndex() == 0) {
82659             return false;
82660         }
82661
82662         this.lastLocation = location;
82663
82664         if ((draggedHeader !== header) &&
82665             ((pos === "before" && nextHd !== header) ||
82666             (pos === "after" && prevHd !== header)) &&
82667             !header.isDescendantOf(draggedHeader)) {
82668
82669             
82670             
82671             
82672             var allDropZones = Ext.dd.DragDropManager.getRelated(this),
82673                 ln = allDropZones.length,
82674                 i  = 0,
82675                 dropZone;
82676
82677             for (; i < ln; i++) {
82678                 dropZone = allDropZones[i];
82679                 if (dropZone !== this && dropZone.invalidateDrop) {
82680                     dropZone.invalidateDrop();
82681                 }
82682             }
82683
82684
82685             this.valid = true;
82686             topIndicator = this.getTopIndicator();
82687             bottomIndicator = this.getBottomIndicator();
82688             if (pos === 'before') {
82689                 topAnchor = 'tl';
82690                 bottomAnchor = 'bl';
82691             } else {
82692                 topAnchor = 'tr';
82693                 bottomAnchor = 'br';
82694             }
82695             topXY = header.el.getAnchorXY(topAnchor);
82696             bottomXY = header.el.getAnchorXY(bottomAnchor);
82697
82698             
82699             headerCtEl = this.headerCt.el;
82700             minX = headerCtEl.getLeft();
82701             maxX = headerCtEl.getRight();
82702
82703             topXY[0] = Ext.Number.constrain(topXY[0], minX, maxX);
82704             bottomXY[0] = Ext.Number.constrain(bottomXY[0], minX, maxX);
82705
82706             
82707             
82708             topXY[0] -= 4;
82709             topXY[1] -= 9;
82710             bottomXY[0] -= 4;
82711
82712             
82713             topIndicator.setXY(topXY);
82714             bottomIndicator.setXY(bottomXY);
82715             topIndicator.show();
82716             bottomIndicator.show();
82717         
82718         } else {
82719             this.invalidateDrop();
82720         }
82721     },
82722
82723     invalidateDrop: function() {
82724         this.valid = false;
82725         this.hideIndicators();
82726     },
82727
82728     onNodeOver: function(node, dragZone, e, data) {
82729         if (data.header.el.dom !== node) {
82730             this.positionIndicator(data.header, node, e);
82731         }
82732         return this.valid ? this.dropAllowed : this.dropNotAllowed;
82733     },
82734
82735     hideIndicators: function() {
82736         this.getTopIndicator().hide();
82737         this.getBottomIndicator().hide();
82738     },
82739
82740     onNodeOut: function() {
82741         this.hideIndicators();
82742     },
82743
82744     onNodeDrop: function(node, dragZone, e, data) {
82745         if (this.valid) {
82746             this.invalidateDrop();
82747             var hd = data.header,
82748                 lastLocation = this.lastLocation,
82749                 fromCt  = hd.ownerCt,
82750                 fromIdx = fromCt.items.indexOf(hd), 
82751                 toCt    = lastLocation.header.ownerCt,
82752                 toIdx   = toCt.items.indexOf(lastLocation.header),
82753                 headerCt = this.headerCt,
82754                 groupCt,
82755                 scrollerOwner;
82756
82757             if (lastLocation.pos === 'after') {
82758                 toIdx++;
82759             }
82760
82761             
82762             
82763             
82764             if (fromCt !== toCt && fromCt.lockableInjected && toCt.lockableInjected && toCt.lockedCt) {
82765                 scrollerOwner = fromCt.up('[scrollerOwner]');
82766                 scrollerOwner.lock(hd, toIdx);
82767             } else if (fromCt !== toCt && fromCt.lockableInjected && toCt.lockableInjected && fromCt.lockedCt) {
82768                 scrollerOwner = fromCt.up('[scrollerOwner]');
82769                 scrollerOwner.unlock(hd, toIdx);
82770             } else {
82771                 
82772                 
82773                 if ((fromCt === toCt) && (toIdx > fromCt.items.indexOf(hd))) {
82774                     toIdx--;
82775                 }
82776
82777                 
82778                 if (fromCt !== toCt) {
82779                     fromCt.suspendLayout = true;
82780                     fromCt.remove(hd, false);
82781                     fromCt.suspendLayout = false;
82782                 }
82783
82784                 
82785                 if (fromCt.isGroupHeader) {
82786                     if (!fromCt.items.getCount()) {
82787                         groupCt = fromCt.ownerCt;
82788                         groupCt.suspendLayout = true;
82789                         groupCt.remove(fromCt, false);
82790                         fromCt.el.dom.parentNode.removeChild(fromCt.el.dom);
82791                         groupCt.suspendLayout = false;
82792                     } else {
82793                         fromCt.minWidth = fromCt.getWidth() - hd.getWidth();
82794                         fromCt.setWidth(fromCt.minWidth);
82795                     }
82796                 }
82797
82798                 
82799                 toCt.suspendLayout = true;
82800                 if (fromCt === toCt) {
82801                     toCt.move(fromIdx, toIdx);
82802                 } else {
82803                     toCt.insert(toIdx, hd);
82804                 }
82805                 toCt.suspendLayout = false;
82806
82807                 
82808                 
82809                 
82810                 if (toCt.isGroupHeader) {
82811                     hd.savedFlex = hd.flex;
82812                     delete hd.flex;
82813                     hd.width = hd.getWidth();
82814                     
82815                     
82816                     toCt.minWidth = toCt.getWidth() + hd.getWidth() - (hd.savedFlex ? 1 : 0);
82817                     toCt.setWidth(toCt.minWidth);
82818                 } else {
82819                     if (hd.savedFlex) {
82820                         hd.flex = hd.savedFlex;
82821                         delete hd.width;
82822                     }
82823                 }
82824
82825
82826                 
82827                 headerCt.purgeCache();
82828                 headerCt.doLayout();
82829                 headerCt.onHeaderMoved(hd, fromIdx, toIdx);
82830                 
82831                 if (!fromCt.items.getCount()) {
82832                     fromCt.destroy();
82833                 }
82834             }
82835         }
82836     }
82837 });
82838
82839
82840 Ext.define('Ext.grid.plugin.Editing', {
82841     alias: 'editing.editing',
82842
82843     requires: [
82844         'Ext.grid.column.Column',
82845         'Ext.util.KeyNav'
82846     ],
82847
82848     mixins: {
82849         observable: 'Ext.util.Observable'
82850     },
82851
82852     
82853     clicksToEdit: 2,
82854
82855     
82856     defaultFieldXType: 'textfield',
82857
82858     
82859     editStyle: '',
82860
82861     constructor: function(config) {
82862         var me = this;
82863         Ext.apply(me, config);
82864
82865         me.addEvents(
82866             
82867             'beforeedit',
82868
82869             
82870             'edit',
82871
82872             
82873             'validateedit'
82874         );
82875         me.mixins.observable.constructor.call(me);
82876         
82877         me.relayEvents(me, ['afteredit'], 'after');
82878     },
82879
82880     
82881     init: function(grid) {
82882         var me = this;
82883
82884         me.grid = grid;
82885         me.view = grid.view;
82886         me.initEvents();
82887         me.mon(grid, 'reconfigure', me.onReconfigure, me);
82888         me.onReconfigure();
82889
82890         grid.relayEvents(me, ['beforeedit', 'edit', 'validateedit']);
82891         
82892         
82893         grid.isEditable = true;
82894         grid.editingPlugin = grid.view.editingPlugin = me;
82895     },
82896
82897     
82898     onReconfigure: function(){
82899         this.initFieldAccessors(this.view.getGridColumns());
82900     },
82901
82902     
82903     destroy: function() {
82904         var me = this,
82905             grid = me.grid,
82906             headerCt = grid.headerCt,
82907             events = grid.events;
82908
82909         Ext.destroy(me.keyNav);
82910         me.removeFieldAccessors(grid.getView().getGridColumns());
82911
82912         
82913         me.clearListeners();
82914
82915         delete me.grid.editingPlugin;
82916         delete me.grid.view.editingPlugin;
82917         delete me.grid;
82918         delete me.view;
82919         delete me.editor;
82920         delete me.keyNav;
82921     },
82922
82923     
82924     getEditStyle: function() {
82925         return this.editStyle;
82926     },
82927
82928     
82929     initFieldAccessors: function(column) {
82930         var me = this;
82931
82932         if (Ext.isArray(column)) {
82933             Ext.Array.forEach(column, me.initFieldAccessors, me);
82934             return;
82935         }
82936
82937         
82938         
82939         Ext.applyIf(column, {
82940             getEditor: function(record, defaultField) {
82941                 return me.getColumnField(this, defaultField);
82942             },
82943
82944             setEditor: function(field) {
82945                 me.setColumnField(this, field);
82946             }
82947         });
82948     },
82949
82950     
82951     removeFieldAccessors: function(column) {
82952         var me = this;
82953
82954         if (Ext.isArray(column)) {
82955             Ext.Array.forEach(column, me.removeFieldAccessors, me);
82956             return;
82957         }
82958
82959         delete column.getEditor;
82960         delete column.setEditor;
82961     },
82962
82963     
82964     
82965     getColumnField: function(columnHeader, defaultField) {
82966         var field = columnHeader.field;
82967
82968         if (!field && columnHeader.editor) {
82969             field = columnHeader.editor;
82970             delete columnHeader.editor;
82971         }
82972
82973         if (!field && defaultField) {
82974             field = defaultField;
82975         }
82976
82977         if (field) {
82978             if (Ext.isString(field)) {
82979                 field = { xtype: field };
82980             }
82981             if (Ext.isObject(field) && !field.isFormField) {
82982                 field = Ext.ComponentManager.create(field, this.defaultFieldXType);
82983                 columnHeader.field = field;
82984             }
82985
82986             Ext.apply(field, {
82987                 name: columnHeader.dataIndex
82988             });
82989
82990             return field;
82991         }
82992     },
82993
82994     
82995     
82996     setColumnField: function(column, field) {
82997         if (Ext.isObject(field) && !field.isFormField) {
82998             field = Ext.ComponentManager.create(field, this.defaultFieldXType);
82999         }
83000         column.field = field;
83001     },
83002
83003     
83004     initEvents: function() {
83005         var me = this;
83006         me.initEditTriggers();
83007         me.initCancelTriggers();
83008     },
83009
83010     
83011     initCancelTriggers: Ext.emptyFn,
83012
83013     
83014     initEditTriggers: function() {
83015         var me = this,
83016             view = me.view,
83017             clickEvent = me.clicksToEdit === 1 ? 'click' : 'dblclick';
83018
83019         
83020         me.mon(view, 'cell' + clickEvent, me.startEditByClick, me);
83021         view.on('render', function() {
83022             me.keyNav = Ext.create('Ext.util.KeyNav', view.el, {
83023                 enter: me.onEnterKey,
83024                 esc: me.onEscKey,
83025                 scope: me
83026             });
83027         }, me, { single: true });
83028     },
83029
83030     
83031     onEnterKey: function(e) {
83032         var me = this,
83033             grid = me.grid,
83034             selModel = grid.getSelectionModel(),
83035             record,
83036             columnHeader = grid.headerCt.getHeaderAtIndex(0);
83037
83038         
83039         
83040         if (selModel.getCurrentPosition) {
83041             pos = selModel.getCurrentPosition();
83042             record = grid.store.getAt(pos.row);
83043             columnHeader = grid.headerCt.getHeaderAtIndex(pos.column);
83044         }
83045         
83046         else {
83047             record = selModel.getLastSelected();
83048         }
83049         me.startEdit(record, columnHeader);
83050     },
83051
83052     
83053     onEscKey: function(e) {
83054         this.cancelEdit();
83055     },
83056
83057     
83058     startEditByClick: function(view, cell, colIdx, record, row, rowIdx, e) {
83059         this.startEdit(record, view.getHeaderAtIndex(colIdx));
83060     },
83061
83062     
83063     beforeEdit: Ext.emptyFn,
83064
83065     
83066     startEdit: function(record, columnHeader) {
83067         var me = this,
83068             context = me.getEditingContext(record, columnHeader);
83069
83070         if (me.beforeEdit(context) === false || me.fireEvent('beforeedit', context) === false || context.cancel) {
83071             return false;
83072         }
83073
83074         me.context = context;
83075         me.editing = true;
83076     },
83077
83078     
83079     getEditingContext: function(record, columnHeader) {
83080         var me = this,
83081             grid = me.grid,
83082             store = grid.store,
83083             rowIdx,
83084             colIdx,
83085             view = grid.getView(),
83086             value;
83087
83088         
83089         if (Ext.isNumber(record)) {
83090             rowIdx = record;
83091             record = store.getAt(rowIdx);
83092         } else {
83093             rowIdx = store.indexOf(record);
83094         }
83095         if (Ext.isNumber(columnHeader)) {
83096             colIdx = columnHeader;
83097             columnHeader = grid.headerCt.getHeaderAtIndex(colIdx);
83098         } else {
83099             colIdx = columnHeader.getIndex();
83100         }
83101
83102         value = record.get(columnHeader.dataIndex);
83103         return {
83104             grid: grid,
83105             record: record,
83106             field: columnHeader.dataIndex,
83107             value: value,
83108             row: view.getNode(rowIdx),
83109             column: columnHeader,
83110             rowIdx: rowIdx,
83111             colIdx: colIdx
83112         };
83113     },
83114
83115     
83116     cancelEdit: function() {
83117         this.editing = false;
83118     },
83119
83120     
83121     completeEdit: function() {
83122         var me = this;
83123
83124         if (me.editing && me.validateEdit()) {
83125             me.fireEvent('edit', me.context);
83126         }
83127
83128         delete me.context;
83129         me.editing = false;
83130     },
83131
83132     
83133     validateEdit: function() {
83134         var me = this,
83135             context = me.context;
83136
83137         return me.fireEvent('validateedit', me, context) !== false && !context.cancel;
83138     }
83139 });
83140
83141
83142 Ext.define('Ext.grid.plugin.CellEditing', {
83143     alias: 'plugin.cellediting',
83144     extend: 'Ext.grid.plugin.Editing',
83145     requires: ['Ext.grid.CellEditor', 'Ext.util.DelayedTask'],
83146
83147     constructor: function() {
83148         
83149         
83150         
83151         this.callParent(arguments);
83152         this.editors = Ext.create('Ext.util.MixedCollection', false, function(editor) {
83153             return editor.editorId;
83154         });
83155         this.editTask = Ext.create('Ext.util.DelayedTask');
83156     },
83157     
83158     onReconfigure: function(){
83159         this.editors.clear();
83160         this.callParent();    
83161     },
83162
83163     
83164     destroy: function() {
83165         var me = this;
83166         me.editTask.cancel();
83167         me.editors.each(Ext.destroy, Ext);
83168         me.editors.clear();
83169         me.callParent(arguments);
83170     },
83171     
83172     onBodyScroll: function() {
83173         var ed = this.getActiveEditor();
83174         if (ed && ed.field) {
83175             if (ed.field.triggerBlur) {
83176                 ed.field.triggerBlur();
83177             } else {
83178                 ed.field.blur();
83179             }
83180         }
83181     },
83182
83183     
83184     
83185     initCancelTriggers: function() {
83186         var me   = this,
83187             grid = me.grid,
83188             view = grid.view;
83189             
83190         view.addElListener('mousewheel', me.cancelEdit, me);
83191         me.mon(view, 'bodyscroll', me.onBodyScroll, me);
83192         me.mon(grid, {
83193             columnresize: me.cancelEdit,
83194             columnmove: me.cancelEdit,
83195             scope: me
83196         });
83197     },
83198
83199     
83200     startEdit: function(record, columnHeader) {
83201         var me = this,
83202             value = record.get(columnHeader.dataIndex),
83203             context = me.getEditingContext(record, columnHeader),
83204             ed;
83205
83206         record = context.record;
83207         columnHeader = context.column;
83208
83209         
83210         
83211         me.completeEdit();
83212
83213         context.originalValue = context.value = value;
83214         if (me.beforeEdit(context) === false || me.fireEvent('beforeedit', context) === false || context.cancel) {
83215             return false;
83216         }
83217         
83218         
83219         if (columnHeader && !columnHeader.getEditor(record)) {
83220             return false;
83221         }
83222         
83223         ed = me.getEditor(record, columnHeader);
83224         if (ed) {
83225             me.context = context;
83226             me.setActiveEditor(ed);
83227             me.setActiveRecord(record);
83228             me.setActiveColumn(columnHeader);
83229
83230             
83231             me.editTask.delay(15, ed.startEdit, ed, [me.getCell(record, columnHeader), value]);
83232         } else {
83233             
83234             
83235             
83236             
83237             me.grid.getView().getEl(columnHeader).focus((Ext.isWebKit || Ext.isIE) ? 10 : false);
83238         }
83239     },
83240
83241     completeEdit: function() {
83242         var activeEd = this.getActiveEditor();
83243         if (activeEd) {
83244             activeEd.completeEdit();
83245         }
83246     },
83247
83248     
83249     setActiveEditor: function(ed) {
83250         this.activeEditor = ed;
83251     },
83252
83253     getActiveEditor: function() {
83254         return this.activeEditor;
83255     },
83256
83257     setActiveColumn: function(column) {
83258         this.activeColumn = column;
83259     },
83260
83261     getActiveColumn: function() {
83262         return this.activeColumn;
83263     },
83264
83265     setActiveRecord: function(record) {
83266         this.activeRecord = record;
83267     },
83268
83269     getActiveRecord: function() {
83270         return this.activeRecord;
83271     },
83272
83273     getEditor: function(record, column) {
83274         var me = this,
83275             editors = me.editors,
83276             editorId = column.getItemId(),
83277             editor = editors.getByKey(editorId);
83278
83279         if (editor) {
83280             return editor;
83281         } else {
83282             editor = column.getEditor(record);
83283             if (!editor) {
83284                 return false;
83285             }
83286
83287             
83288             if (!(editor instanceof Ext.grid.CellEditor)) {
83289                 editor = Ext.create('Ext.grid.CellEditor', {
83290                     editorId: editorId,
83291                     field: editor
83292                 });
83293             }
83294             editor.parentEl = me.grid.getEditorParent();
83295             
83296             editor.on({
83297                 scope: me,
83298                 specialkey: me.onSpecialKey,
83299                 complete: me.onEditComplete,
83300                 canceledit: me.cancelEdit
83301             });
83302             editors.add(editor);
83303             return editor;
83304         }
83305     },
83306     
83307     
83308     setColumnField: function(column, field) {
83309         var ed = this.editors.getByKey(column.getItemId());
83310         Ext.destroy(ed, column.field);
83311         this.editors.removeAtKey(column.getItemId());
83312         this.callParent(arguments);
83313     },
83314
83315     
83316     getCell: function(record, column) {
83317         return this.grid.getView().getCell(record, column);
83318     },
83319
83320     onSpecialKey: function(ed, field, e) {
83321         var grid = this.grid,
83322             sm;
83323         if (e.getKey() === e.TAB) {
83324             e.stopEvent();
83325             sm = grid.getSelectionModel();
83326             if (sm.onEditorTab) {
83327                 sm.onEditorTab(this, e);
83328             }
83329         }
83330     },
83331
83332     onEditComplete : function(ed, value, startValue) {
83333         var me = this,
83334             grid = me.grid,
83335             sm = grid.getSelectionModel(),
83336             activeColumn = me.getActiveColumn(),
83337             dataIndex;
83338
83339         if (activeColumn) {
83340             dataIndex = activeColumn.dataIndex;
83341
83342             me.setActiveEditor(null);
83343             me.setActiveColumn(null);
83344             me.setActiveRecord(null);
83345             delete sm.wasEditing;
83346     
83347             if (!me.validateEdit()) {
83348                 return;
83349             }
83350             
83351             
83352             if (value !== startValue) {
83353                 me.context.record.set(dataIndex, value);
83354             
83355             } else {
83356                 grid.getView().getEl(activeColumn).focus();
83357             }
83358             me.context.value = value;
83359             me.fireEvent('edit', me, me.context);
83360         }
83361     },
83362
83363     
83364     cancelEdit: function() {
83365         var me = this,
83366             activeEd = me.getActiveEditor(),
83367             viewEl = me.grid.getView().getEl(me.getActiveColumn());
83368
83369         me.setActiveEditor(null);
83370         me.setActiveColumn(null);
83371         me.setActiveRecord(null);
83372         if (activeEd) {
83373             activeEd.cancelEdit();
83374             viewEl.focus();
83375         }
83376     },
83377
83378     
83379     startEditByPosition: function(position) {
83380         var me = this,
83381             grid = me.grid,
83382             sm = grid.getSelectionModel(),
83383             editRecord = grid.store.getAt(position.row),
83384             editColumnHeader = grid.headerCt.getHeaderAtIndex(position.column);
83385
83386         if (sm.selectByPosition) {
83387             sm.selectByPosition(position);
83388         }
83389         me.startEdit(editRecord, editColumnHeader);
83390     }
83391 });
83392
83393 Ext.define('Ext.grid.plugin.DragDrop', {
83394     extend: 'Ext.AbstractPlugin',
83395     alias: 'plugin.gridviewdragdrop',
83396
83397     uses: [
83398         'Ext.view.DragZone',
83399         'Ext.grid.ViewDropZone'
83400     ],
83401
83402     
83403
83404     
83405
83406     dragText : '{0} selected row{1}',
83407
83408     
83409     ddGroup : "GridDD",
83410
83411     
83412
83413     
83414
83415     
83416     enableDrop: true,
83417
83418     
83419     enableDrag: true,
83420
83421     init : function(view) {
83422         view.on('render', this.onViewRender, this, {single: true});
83423     },
83424
83425     
83426     destroy: function() {
83427         Ext.destroy(this.dragZone, this.dropZone);
83428     },
83429
83430     enable: function() {
83431         var me = this;
83432         if (me.dragZone) {
83433             me.dragZone.unlock();
83434         }
83435         if (me.dropZone) {
83436             me.dropZone.unlock();
83437         }
83438         me.callParent();
83439     },
83440
83441     disable: function() {
83442         var me = this;
83443         if (me.dragZone) {
83444             me.dragZone.lock();
83445         }
83446         if (me.dropZone) {
83447             me.dropZone.lock();
83448         }
83449         me.callParent();
83450     },
83451
83452     onViewRender : function(view) {
83453         var me = this;
83454
83455         if (me.enableDrag) {
83456             me.dragZone = Ext.create('Ext.view.DragZone', {
83457                 view: view,
83458                 ddGroup: me.dragGroup || me.ddGroup,
83459                 dragText: me.dragText
83460             });
83461         }
83462
83463         if (me.enableDrop) {
83464             me.dropZone = Ext.create('Ext.grid.ViewDropZone', {
83465                 view: view,
83466                 ddGroup: me.dropGroup || me.ddGroup
83467             });
83468         }
83469     }
83470 });
83471
83472 Ext.define('Ext.grid.plugin.HeaderReorderer', {
83473     extend: 'Ext.util.Observable',
83474     requires: ['Ext.grid.header.DragZone', 'Ext.grid.header.DropZone'],
83475     alias: 'plugin.gridheaderreorderer',
83476
83477     init: function(headerCt) {
83478         this.headerCt = headerCt;
83479         headerCt.on('render', this.onHeaderCtRender, this);
83480     },
83481
83482     
83483     destroy: function() {
83484         Ext.destroy(this.dragZone, this.dropZone);
83485     },
83486
83487     onHeaderCtRender: function() {
83488         this.dragZone = Ext.create('Ext.grid.header.DragZone', this.headerCt);
83489         this.dropZone = Ext.create('Ext.grid.header.DropZone', this.headerCt);
83490         if (this.disabled) {
83491             this.dragZone.disable();
83492         }
83493     },
83494     
83495     enable: function() {
83496         this.disabled = false;
83497         if (this.dragZone) {
83498             this.dragZone.enable();
83499         }
83500     },
83501     
83502     disable: function() {
83503         this.disabled = true;
83504         if (this.dragZone) {
83505             this.dragZone.disable();
83506         }
83507     }
83508 });
83509
83510 Ext.define('Ext.grid.plugin.HeaderResizer', {
83511     extend: 'Ext.util.Observable',
83512     requires: ['Ext.dd.DragTracker', 'Ext.util.Region'],
83513     alias: 'plugin.gridheaderresizer',
83514
83515     disabled: false,
83516
83517     
83518     configs: {
83519         dynamic: true
83520     },
83521
83522     colHeaderCls: Ext.baseCSSPrefix + 'column-header',
83523
83524     minColWidth: 40,
83525     maxColWidth: 1000,
83526     wResizeCursor: 'col-resize',
83527     eResizeCursor: 'col-resize',
83528     
83529     
83530     
83531     
83532
83533     init: function(headerCt) {
83534         this.headerCt = headerCt;
83535         headerCt.on('render', this.afterHeaderRender, this, {single: true});
83536     },
83537
83538     
83539     destroy: function() {
83540         if (this.tracker) {
83541             this.tracker.destroy();
83542         }
83543     },
83544
83545     afterHeaderRender: function() {
83546         var headerCt = this.headerCt,
83547             el = headerCt.el;
83548
83549         headerCt.mon(el, 'mousemove', this.onHeaderCtMouseMove, this);
83550
83551         this.tracker = Ext.create('Ext.dd.DragTracker', {
83552             disabled: this.disabled,
83553             onBeforeStart: Ext.Function.bind(this.onBeforeStart, this),
83554             onStart: Ext.Function.bind(this.onStart, this),
83555             onDrag: Ext.Function.bind(this.onDrag, this),
83556             onEnd: Ext.Function.bind(this.onEnd, this),
83557             tolerance: 3,
83558             autoStart: 300,
83559             el: el
83560         });
83561     },
83562
83563     
83564     
83565     
83566     onHeaderCtMouseMove: function(e, t) {
83567         if (this.headerCt.dragging) {
83568             if (this.activeHd) {
83569                 this.activeHd.el.dom.style.cursor = '';
83570                 delete this.activeHd;
83571             }
83572         } else {
83573             var headerEl = e.getTarget('.' + this.colHeaderCls, 3, true),
83574                 overHeader, resizeHeader;
83575
83576             if (headerEl){
83577                 overHeader = Ext.getCmp(headerEl.id);
83578
83579                 
83580                 if (overHeader.isOnLeftEdge(e)) {
83581                     resizeHeader = overHeader.previousNode('gridcolumn:not([hidden])');
83582
83583                 }
83584                 
83585                 else if (overHeader.isOnRightEdge(e)) {
83586                     resizeHeader = overHeader;
83587                 }
83588                 
83589                 else {
83590                     resizeHeader = null;
83591                 }
83592
83593                 
83594                 if (resizeHeader) {
83595                     
83596                     
83597                     
83598                     if (resizeHeader.isGroupHeader) {
83599                         resizeHeader = resizeHeader.down(':not([isGroupHeader]):not([hidden]):last');
83600                     }
83601
83602                     
83603                     
83604                     if (resizeHeader && !(resizeHeader.fixed || (resizeHeader.resizable === false) || this.disabled)) {
83605                         this.activeHd = resizeHeader;
83606                         overHeader.el.dom.style.cursor = this.eResizeCursor;
83607                     }
83608                 
83609                 } else {
83610                     overHeader.el.dom.style.cursor = '';
83611                     delete this.activeHd;
83612                 }
83613             }
83614         }
83615     },
83616
83617     
83618     onBeforeStart : function(e){
83619         var t = e.getTarget();
83620         
83621         this.dragHd = this.activeHd;
83622
83623         if (!!this.dragHd && !Ext.fly(t).hasCls('x-column-header-trigger') && !this.headerCt.dragging) {
83624             
83625             this.tracker.constrainTo = this.getConstrainRegion();
83626             return true;
83627         } else {
83628             this.headerCt.dragging = false;
83629             return false;
83630         }
83631     },
83632
83633     
83634     getConstrainRegion: function() {
83635         var dragHdEl = this.dragHd.el,
83636             region   = Ext.util.Region.getRegion(dragHdEl);
83637
83638         return region.adjust(
83639             0,
83640             this.maxColWidth - dragHdEl.getWidth(),
83641             0,
83642             this.minColWidth
83643         );
83644     },
83645
83646     
83647     
83648     onStart: function(e){
83649         var me       = this,
83650             dragHd   = me.dragHd,
83651             dragHdEl = dragHd.el,
83652             width    = dragHdEl.getWidth(),
83653             headerCt = me.headerCt,
83654             t        = e.getTarget();
83655
83656         if (me.dragHd && !Ext.fly(t).hasCls('x-column-header-trigger')) {
83657             headerCt.dragging = true;
83658         }
83659
83660         me.origWidth = width;
83661
83662         
83663         if (!me.dynamic) {
83664             var xy           = dragHdEl.getXY(),
83665                 gridSection  = headerCt.up('[scrollerOwner]'),
83666                 dragHct      = me.dragHd.up(':not([isGroupHeader])'),
83667                 firstSection = dragHct.up(),
83668                 lhsMarker    = gridSection.getLhsMarker(),
83669                 rhsMarker    = gridSection.getRhsMarker(),
83670                 el           = rhsMarker.parent(),
83671                 offsetLeft   = el.getLeft(true),
83672                 offsetTop    = el.getTop(true),
83673                 topLeft      = el.translatePoints(xy),
83674                 markerHeight = firstSection.body.getHeight() + headerCt.getHeight(),
83675                 top = topLeft.top - offsetTop;
83676
83677             lhsMarker.setTop(top);
83678             rhsMarker.setTop(top);
83679             lhsMarker.setHeight(markerHeight);
83680             rhsMarker.setHeight(markerHeight);
83681             lhsMarker.setLeft(topLeft.left - offsetLeft);
83682             rhsMarker.setLeft(topLeft.left + width - offsetLeft);
83683         }
83684     },
83685
83686     
83687     onDrag: function(e){
83688         if (!this.dynamic) {
83689             var xy          = this.tracker.getXY('point'),
83690                 gridSection = this.headerCt.up('[scrollerOwner]'),
83691                 rhsMarker   = gridSection.getRhsMarker(),
83692                 el          = rhsMarker.parent(),
83693                 topLeft     = el.translatePoints(xy),
83694                 offsetLeft  = el.getLeft(true);
83695
83696             rhsMarker.setLeft(topLeft.left - offsetLeft);
83697         
83698         } else {
83699             this.doResize();
83700         }
83701     },
83702
83703     onEnd: function(e){
83704         this.headerCt.dragging = false;
83705         if (this.dragHd) {
83706             if (!this.dynamic) {
83707                 var dragHd      = this.dragHd,
83708                     gridSection = this.headerCt.up('[scrollerOwner]'),
83709                     lhsMarker   = gridSection.getLhsMarker(),
83710                     rhsMarker   = gridSection.getRhsMarker(),
83711                     currWidth   = dragHd.getWidth(),
83712                     offset      = this.tracker.getOffset('point'),
83713                     offscreen   = -9999;
83714
83715                 
83716                 lhsMarker.setLeft(offscreen);
83717                 rhsMarker.setLeft(offscreen);
83718             }
83719             this.doResize();
83720         }
83721     },
83722
83723     doResize: function() {
83724         if (this.dragHd) {
83725             var dragHd = this.dragHd,
83726                 nextHd,
83727                 offset = this.tracker.getOffset('point');
83728
83729             
83730             if (dragHd.flex) {
83731                 delete dragHd.flex;
83732             }
83733
83734             this.headerCt.suspendLayout = true;
83735             dragHd.setWidth(this.origWidth + offset[0], false);
83736
83737             
83738             
83739             
83740             
83741             if (this.headerCt.forceFit) {
83742                 nextHd = dragHd.nextNode('gridcolumn:not([hidden]):not([isGroupHeader])');
83743                 if (nextHd) {
83744                     delete nextHd.flex;
83745                     nextHd.setWidth(nextHd.getWidth() - offset[0], false);
83746                 }
83747             }
83748             this.headerCt.suspendLayout = false;
83749             this.headerCt.doComponentLayout(this.headerCt.getFullWidth());
83750         }
83751     },
83752
83753     disable: function() {
83754         this.disabled = true;
83755         if (this.tracker) {
83756             this.tracker.disable();
83757         }
83758     },
83759
83760     enable: function() {
83761         this.disabled = false;
83762         if (this.tracker) {
83763             this.tracker.enable();
83764         }
83765     }
83766 });
83767
83768 Ext.define('Ext.grid.plugin.RowEditing', {
83769     extend: 'Ext.grid.plugin.Editing',
83770     alias: 'plugin.rowediting',
83771
83772     requires: [
83773         'Ext.grid.RowEditor'
83774     ],
83775
83776     editStyle: 'row',
83777
83778     
83779     autoCancel: true,
83780
83781     
83782
83783     
83784     errorSummary: true,
83785
83786     
83787     
83788     
83789     
83790     
83791     
83792
83793     constructor: function() {
83794         var me = this;
83795         me.callParent(arguments);
83796
83797         if (!me.clicksToMoveEditor) {
83798             me.clicksToMoveEditor = me.clicksToEdit;
83799         }
83800
83801         me.autoCancel = !!me.autoCancel;
83802     },
83803
83804     
83805     destroy: function() {
83806         var me = this;
83807         Ext.destroy(me.editor);
83808         me.callParent(arguments);
83809     },
83810
83811     
83812     startEdit: function(record, columnHeader) {
83813         var me = this,
83814             editor = me.getEditor();
83815
83816         if (me.callParent(arguments) === false) {
83817             return false;
83818         }
83819
83820         
83821         if (editor.beforeEdit() !== false) {
83822             editor.startEdit(me.context.record, me.context.column);
83823         }
83824     },
83825
83826     
83827     cancelEdit: function() {
83828         var me = this;
83829
83830         if (me.editing) {
83831             me.getEditor().cancelEdit();
83832             me.callParent(arguments);
83833             
83834             me.fireEvent('canceledit', me.context);
83835         }
83836     },
83837
83838     
83839     completeEdit: function() {
83840         var me = this;
83841
83842         if (me.editing && me.validateEdit()) {
83843             me.editing = false;
83844             me.fireEvent('edit', me.context);
83845         }
83846     },
83847
83848     
83849     validateEdit: function() {
83850         var me             = this,
83851             editor         = me.editor,
83852             context        = me.context,
83853             record         = context.record,
83854             newValues      = {},
83855             originalValues = {},
83856             name;
83857
83858         editor.items.each(function(item) {
83859             name = item.name;
83860
83861             newValues[name]      = item.getValue();
83862             originalValues[name] = record.get(name);
83863         });
83864
83865         Ext.apply(context, {
83866             newValues      : newValues,
83867             originalValues : originalValues
83868         });
83869
83870         return me.callParent(arguments) && me.getEditor().completeEdit();
83871     },
83872
83873     
83874     getEditor: function() {
83875         var me = this;
83876
83877         if (!me.editor) {
83878             me.editor = me.initEditor();
83879         }
83880         return me.editor;
83881     },
83882
83883     
83884     initEditor: function() {
83885         var me = this,
83886             grid = me.grid,
83887             view = me.view,
83888             headerCt = grid.headerCt;
83889
83890         return Ext.create('Ext.grid.RowEditor', {
83891             autoCancel: me.autoCancel,
83892             errorSummary: me.errorSummary,
83893             fields: headerCt.getGridColumns(),
83894             hidden: true,
83895
83896             
83897             editingPlugin: me,
83898             renderTo: view.el
83899         });
83900     },
83901
83902     
83903     initEditTriggers: function() {
83904         var me = this,
83905             grid = me.grid,
83906             view = me.view,
83907             headerCt = grid.headerCt,
83908             moveEditorEvent = me.clicksToMoveEditor === 1 ? 'click' : 'dblclick';
83909
83910         me.callParent(arguments);
83911
83912         if (me.clicksToMoveEditor !== me.clicksToEdit) {
83913             me.mon(view, 'cell' + moveEditorEvent, me.moveEditorByClick, me);
83914         }
83915
83916         view.on('render', function() {
83917             
83918             me.mon(headerCt, {
83919                 add: me.onColumnAdd,
83920                 remove: me.onColumnRemove,
83921                 columnresize: me.onColumnResize,
83922                 columnhide: me.onColumnHide,
83923                 columnshow: me.onColumnShow,
83924                 columnmove: me.onColumnMove,
83925                 scope: me
83926             });
83927         }, me, { single: true });
83928     },
83929
83930     startEditByClick: function() {
83931         var me = this;
83932         if (!me.editing || me.clicksToMoveEditor === me.clicksToEdit) {
83933             me.callParent(arguments);
83934         }
83935     },
83936
83937     moveEditorByClick: function() {
83938         var me = this;
83939         if (me.editing) {
83940             me.superclass.startEditByClick.apply(me, arguments);
83941         }
83942     },
83943
83944     
83945     onColumnAdd: function(ct, column) {
83946         if (column.isHeader) {
83947             var me = this,
83948                 editor;
83949
83950             me.initFieldAccessors(column);
83951             editor = me.getEditor();
83952
83953             if (editor && editor.onColumnAdd) {
83954                 editor.onColumnAdd(column);
83955             }
83956         }
83957     },
83958
83959     
83960     onColumnRemove: function(ct, column) {
83961         if (column.isHeader) {
83962             var me = this,
83963                 editor = me.getEditor();
83964
83965             if (editor && editor.onColumnRemove) {
83966                 editor.onColumnRemove(column);
83967             }
83968             me.removeFieldAccessors(column);
83969         }
83970     },
83971
83972     
83973     onColumnResize: function(ct, column, width) {
83974         if (column.isHeader) {
83975             var me = this,
83976                 editor = me.getEditor();
83977
83978             if (editor && editor.onColumnResize) {
83979                 editor.onColumnResize(column, width);
83980             }
83981         }
83982     },
83983
83984     
83985     onColumnHide: function(ct, column) {
83986         
83987         var me = this,
83988             editor = me.getEditor();
83989
83990         if (editor && editor.onColumnHide) {
83991             editor.onColumnHide(column);
83992         }
83993     },
83994
83995     
83996     onColumnShow: function(ct, column) {
83997         
83998         var me = this,
83999             editor = me.getEditor();
84000
84001         if (editor && editor.onColumnShow) {
84002             editor.onColumnShow(column);
84003         }
84004     },
84005
84006     
84007     onColumnMove: function(ct, column, fromIdx, toIdx) {
84008         
84009         var me = this,
84010             editor = me.getEditor();
84011
84012         if (editor && editor.onColumnMove) {
84013             editor.onColumnMove(column, fromIdx, toIdx);
84014         }
84015     },
84016
84017     
84018     setColumnField: function(column, field) {
84019         var me = this;
84020         me.callParent(arguments);
84021         me.getEditor().setField(column.field, column);
84022     }
84023 });
84024
84025
84026 Ext.define('Ext.grid.property.Grid', {
84027
84028     extend: 'Ext.grid.Panel',
84029
84030     alias: 'widget.propertygrid',
84031
84032     alternateClassName: 'Ext.grid.PropertyGrid',
84033
84034     uses: [
84035        'Ext.grid.plugin.CellEditing',
84036        'Ext.grid.property.Store',
84037        'Ext.grid.property.HeaderContainer',
84038        'Ext.XTemplate',
84039        'Ext.grid.CellEditor',
84040        'Ext.form.field.Date',
84041        'Ext.form.field.Text',
84042        'Ext.form.field.Number'
84043     ],
84044
84045    
84046
84047     
84048
84049     
84050
84051     
84052
84053     
84054
84055     
84056     valueField: 'value',
84057
84058     
84059     nameField: 'name',
84060
84061     
84062
84063     
84064     enableColumnMove: false,
84065     columnLines: true,
84066     stripeRows: false,
84067     trackMouseOver: false,
84068     clicksToEdit: 1,
84069     enableHdMenu: false,
84070
84071     
84072     initComponent : function(){
84073         var me = this;
84074
84075         me.addCls(Ext.baseCSSPrefix + 'property-grid');
84076         me.plugins = me.plugins || [];
84077
84078         
84079         me.plugins.push(Ext.create('Ext.grid.plugin.CellEditing', {
84080             clicksToEdit: me.clicksToEdit,
84081
84082             
84083             startEdit: function(record, column) {
84084                 
84085                 return this.self.prototype.startEdit.call(this, record, me.headerCt.child('#' + me.valueField));
84086             }
84087         }));
84088
84089         me.selModel = {
84090             selType: 'cellmodel',
84091             onCellSelect: function(position) {
84092                 if (position.column != 1) {
84093                     position.column = 1;
84094                 }
84095                 return this.self.prototype.onCellSelect.call(this, position);
84096             }
84097         };
84098         me.customRenderers = me.customRenderers || {};
84099         me.customEditors = me.customEditors || {};
84100
84101         
84102         if (!me.store) {
84103             me.propStore = me.store = Ext.create('Ext.grid.property.Store', me, me.source);
84104         }
84105
84106         me.store.sort('name', 'ASC');
84107         me.columns = Ext.create('Ext.grid.property.HeaderContainer', me, me.store);
84108
84109         me.addEvents(
84110             
84111             'beforepropertychange',
84112             
84113             'propertychange'
84114         );
84115         me.callParent();
84116
84117         
84118         me.getView().walkCells = this.walkCells;
84119
84120         
84121         me.editors = {
84122             'date'    : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Date',   {selectOnFocus: true})}),
84123             'string'  : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Text',   {selectOnFocus: true})}),
84124             'number'  : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Number', {selectOnFocus: true})}),
84125             'boolean' : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.ComboBox', {
84126                 editable: false,
84127                 store: [[ true, me.headerCt.trueText ], [false, me.headerCt.falseText ]]
84128             })})
84129         };
84130
84131         
84132         me.store.on('update', me.onUpdate, me);
84133     },
84134
84135     
84136     onUpdate : function(store, record, operation) {
84137         var me = this,
84138             v, oldValue;
84139
84140         if (operation == Ext.data.Model.EDIT) {
84141             v = record.get(me.valueField);
84142             oldValue = record.modified.value;
84143             if (me.fireEvent('beforepropertychange', me.source, record.getId(), v, oldValue) !== false) {
84144                 if (me.source) {
84145                     me.source[record.getId()] = v;
84146                 }
84147                 record.commit();
84148                 me.fireEvent('propertychange', me.source, record.getId(), v, oldValue);
84149             } else {
84150                 record.reject();
84151             }
84152         }
84153     },
84154
84155     
84156     walkCells: function(pos, direction, e, preventWrap, verifierFn, scope) {
84157         if (direction == 'left') {
84158             direction = 'up';
84159         } else if (direction == 'right') {
84160             direction = 'down';
84161         }
84162         pos = Ext.view.Table.prototype.walkCells.call(this, pos, direction, e, preventWrap, verifierFn, scope);
84163         if (!pos.column) {
84164             pos.column = 1;
84165         }
84166         return pos;
84167     },
84168
84169     
84170     
84171     getCellEditor : function(record, column) {
84172         var me = this,
84173             propName = record.get(me.nameField),
84174             val = record.get(me.valueField),
84175             editor = me.customEditors[propName];
84176
84177         
84178         
84179         if (editor) {
84180             if (!(editor instanceof Ext.grid.CellEditor)) {
84181                 if (!(editor instanceof Ext.form.field.Base)) {
84182                     editor = Ext.ComponentManager.create(editor, 'textfield');
84183                 }
84184                 editor = me.customEditors[propName] = Ext.create('Ext.grid.CellEditor', { field: editor });
84185             }
84186         } else if (Ext.isDate(val)) {
84187             editor = me.editors.date;
84188         } else if (Ext.isNumber(val)) {
84189             editor = me.editors.number;
84190         } else if (Ext.isBoolean(val)) {
84191             editor = me.editors['boolean'];
84192         } else {
84193             editor = me.editors.string;
84194         }
84195
84196         
84197         editor.editorId = propName;
84198         return editor;
84199     },
84200
84201     beforeDestroy: function() {
84202         var me = this;
84203         me.callParent();
84204         me.destroyEditors(me.editors);
84205         me.destroyEditors(me.customEditors);
84206         delete me.source;
84207     },
84208
84209     destroyEditors: function (editors) {
84210         for (var ed in editors) {
84211             if (editors.hasOwnProperty(ed)) {
84212                 Ext.destroy(editors[ed]);
84213             }
84214         }
84215     },
84216
84217     
84218     setSource: function(source) {
84219         this.source = source;
84220         this.propStore.setSource(source);
84221     },
84222
84223     
84224     getSource: function() {
84225         return this.propStore.getSource();
84226     },
84227
84228     
84229     setProperty: function(prop, value, create) {
84230         this.propStore.setValue(prop, value, create);
84231     },
84232
84233     
84234     removeProperty: function(prop) {
84235         this.propStore.remove(prop);
84236     }
84237
84238     
84239     
84240     
84241     
84242 });
84243
84244 Ext.define('Ext.grid.property.HeaderContainer', {
84245
84246     extend: 'Ext.grid.header.Container',
84247
84248     alternateClassName: 'Ext.grid.PropertyColumnModel',
84249     
84250     nameWidth: 115,
84251
84252     
84253     nameText : 'Name',
84254     valueText : 'Value',
84255     dateFormat : 'm/j/Y',
84256     trueText: 'true',
84257     falseText: 'false',
84258
84259     
84260     nameColumnCls: Ext.baseCSSPrefix + 'grid-property-name',
84261
84262     
84263     constructor : function(grid, store) {
84264         var me = this;
84265         
84266         me.grid = grid;
84267         me.store = store;
84268         me.callParent([{
84269             items: [{
84270                 header: me.nameText,
84271                 width: grid.nameColumnWidth || me.nameWidth,
84272                 sortable: true,
84273                 dataIndex: grid.nameField,
84274                 renderer: Ext.Function.bind(me.renderProp, me),
84275                 itemId: grid.nameField,
84276                 menuDisabled :true,
84277                 tdCls: me.nameColumnCls
84278             }, {
84279                 header: me.valueText,
84280                 renderer: Ext.Function.bind(me.renderCell, me),
84281                 getEditor: Ext.Function.bind(me.getCellEditor, me),
84282                 flex: 1,
84283                 fixed: true,
84284                 dataIndex: grid.valueField,
84285                 itemId: grid.valueField,
84286                 menuDisabled: true
84287             }]
84288         }]);
84289     },
84290     
84291     getCellEditor: function(record){
84292         return this.grid.getCellEditor(record, this);
84293     },
84294
84295     
84296     
84297     renderProp : function(v) {
84298         return this.getPropertyName(v);
84299     },
84300
84301     
84302     
84303     renderCell : function(val, meta, rec) {
84304         var me = this,
84305             renderer = me.grid.customRenderers[rec.get(me.grid.nameField)],
84306             result = val;
84307
84308         if (renderer) {
84309             return renderer.apply(me, arguments);
84310         }
84311         if (Ext.isDate(val)) {
84312             result = me.renderDate(val);
84313         } else if (Ext.isBoolean(val)) {
84314             result = me.renderBool(val);
84315         }
84316         return Ext.util.Format.htmlEncode(result);
84317     },
84318
84319     
84320     renderDate : Ext.util.Format.date,
84321
84322     
84323     renderBool : function(bVal) {
84324         return this[bVal ? 'trueText' : 'falseText'];
84325     },
84326
84327     
84328     
84329     getPropertyName : function(name) {
84330         var pn = this.grid.propertyNames;
84331         return pn && pn[name] ? pn[name] : name;
84332     }
84333 });
84334
84335 Ext.define('Ext.grid.property.Property', {
84336     extend: 'Ext.data.Model',
84337
84338     alternateClassName: 'Ext.PropGridProperty',
84339
84340     fields: [{
84341         name: 'name',
84342         type: 'string'
84343     }, {
84344         name: 'value'
84345     }],
84346     idProperty: 'name'
84347 });
84348
84349 Ext.define('Ext.grid.property.Store', {
84350
84351     extend: 'Ext.data.Store',
84352
84353     alternateClassName: 'Ext.grid.PropertyStore',
84354
84355     uses: ['Ext.data.reader.Reader', 'Ext.data.proxy.Proxy', 'Ext.data.ResultSet', 'Ext.grid.property.Property'],
84356
84357     
84358     constructor : function(grid, source){
84359         var me = this;
84360         
84361         me.grid = grid;
84362         me.source = source;
84363         me.callParent([{
84364             data: source,
84365             model: Ext.grid.property.Property,
84366             proxy: me.getProxy()
84367         }]);
84368     },
84369
84370     
84371     getProxy: function() {
84372         if (!this.proxy) {
84373             Ext.grid.property.Store.prototype.proxy = Ext.create('Ext.data.proxy.Memory', {
84374                 model: Ext.grid.property.Property,
84375                 reader: this.getReader()
84376             });
84377         }
84378         return this.proxy;
84379     },
84380
84381     
84382     getReader: function() {
84383         if (!this.reader) {
84384             Ext.grid.property.Store.prototype.reader = Ext.create('Ext.data.reader.Reader', {
84385                 model: Ext.grid.property.Property,
84386
84387                 buildExtractors: Ext.emptyFn,
84388
84389                 read: function(dataObject) {
84390                     return this.readRecords(dataObject);
84391                 },
84392
84393                 readRecords: function(dataObject) {
84394                     var val,
84395                         propName,
84396                         result = {
84397                             records: [],
84398                             success: true
84399                         };
84400
84401                     for (propName in dataObject) {
84402                         if (dataObject.hasOwnProperty(propName)) {
84403                             val = dataObject[propName];
84404                             if (this.isEditableValue(val)) {
84405                                 result.records.push(new Ext.grid.property.Property({
84406                                     name: propName,
84407                                     value: val
84408                                 }, propName));
84409                             }
84410                         }
84411                     }
84412                     result.total = result.count = result.records.length;
84413                     return Ext.create('Ext.data.ResultSet', result);
84414                 },
84415
84416                 
84417                 isEditableValue: function(val){
84418                     return Ext.isPrimitive(val) || Ext.isDate(val);
84419                 }
84420             });
84421         }
84422         return this.reader;
84423     },
84424
84425     
84426     setSource : function(dataObject) {
84427         var me = this;
84428
84429         me.source = dataObject;
84430         me.suspendEvents();
84431         me.removeAll();
84432         me.proxy.data = dataObject;
84433         me.load();
84434         me.resumeEvents();
84435         me.fireEvent('datachanged', me);
84436     },
84437
84438     
84439     getProperty : function(row) {
84440        return Ext.isNumber(row) ? this.getAt(row) : this.getById(row);
84441     },
84442
84443     
84444     setValue : function(prop, value, create){
84445         var me = this,
84446             rec = me.getRec(prop);
84447             
84448         if (rec) {
84449             rec.set('value', value);
84450             me.source[prop] = value;
84451         } else if (create) {
84452             
84453             me.source[prop] = value;
84454             rec = new Ext.grid.property.Property({name: prop, value: value}, prop);
84455             me.add(rec);
84456         }
84457     },
84458
84459     
84460     remove : function(prop) {
84461         var rec = this.getRec(prop);
84462         if (rec) {
84463             this.callParent([rec]);
84464             delete this.source[prop];
84465         }
84466     },
84467
84468     
84469     getRec : function(prop) {
84470         return this.getById(prop);
84471     },
84472
84473     
84474     getSource : function() {
84475         return this.source;
84476     }
84477 });
84478
84479
84480 Ext.define('Ext.layout.component.Body', {
84481
84482     
84483
84484     alias: ['layout.body'],
84485
84486     extend: 'Ext.layout.component.Component',
84487
84488     uses: ['Ext.layout.container.Container'],
84489
84490     
84491
84492     type: 'body',
84493     
84494     onLayout: function(width, height) {
84495         var me = this,
84496             owner = me.owner;
84497
84498         
84499         me.setTargetSize(width, height);
84500
84501         
84502         me.setBodySize.apply(me, arguments);
84503
84504         
84505         if (owner && owner.layout && owner.layout.isLayout) {
84506             if (!Ext.isNumber(owner.height) || !Ext.isNumber(owner.width)) {
84507                 owner.layout.bindToOwnerCtComponent = true;
84508             }
84509             else {
84510                 owner.layout.bindToOwnerCtComponent = false;
84511             }
84512         }
84513         
84514         me.callParent(arguments);
84515     },
84516
84517     
84518     setBodySize: function(width, height) {
84519         var me = this,
84520             owner = me.owner,
84521             frameSize = owner.frameSize,
84522             isNumber = Ext.isNumber;
84523
84524         if (isNumber(width)) {
84525             width -= owner.el.getFrameWidth('lr') - frameSize.left - frameSize.right;
84526         }
84527         if (isNumber(height)) {
84528             height -= owner.el.getFrameWidth('tb') - frameSize.top - frameSize.bottom;
84529         }
84530
84531         me.setElementSize(owner.body, width, height);
84532     }
84533 });
84534
84535 Ext.define('Ext.layout.component.FieldSet', {
84536     extend: 'Ext.layout.component.Body',
84537     alias: ['layout.fieldset'],
84538
84539     type: 'fieldset',
84540
84541     doContainerLayout: function() {
84542         
84543         if (!this.owner.collapsed) {
84544             this.callParent();
84545         }
84546     }
84547 });
84548
84549 Ext.define('Ext.layout.component.Tab', {
84550
84551     alias: ['layout.tab'],
84552
84553     extend: 'Ext.layout.component.Button',
84554
84555     
84556
84557     beforeLayout: function() {
84558         var me = this, dirty = me.lastClosable !== me.owner.closable;
84559
84560         if (dirty) {
84561             delete me.adjWidth;
84562         }
84563
84564         return this.callParent(arguments) || dirty;
84565     },
84566
84567     onLayout: function () {
84568         var me = this;
84569
84570         me.callParent(arguments);
84571
84572         me.lastClosable = me.owner.closable;
84573     }
84574 });
84575
84576
84577 Ext.define('Ext.layout.component.field.File', {
84578     alias: ['layout.filefield'],
84579     extend: 'Ext.layout.component.field.Field',
84580
84581     type: 'filefield',
84582
84583     sizeBodyContents: function(width, height) {
84584         var me = this,
84585             owner = me.owner;
84586
84587         if (!owner.buttonOnly) {
84588             
84589             
84590             me.setElementSize(owner.inputEl, Ext.isNumber(width) ? width - owner.button.getWidth() - owner.buttonMargin : width);
84591         }
84592     }
84593 });
84594
84595
84596 Ext.define('Ext.layout.component.field.Slider', {
84597
84598     
84599
84600     alias: ['layout.sliderfield'],
84601
84602     extend: 'Ext.layout.component.field.Field',
84603
84604     
84605
84606     type: 'sliderfield',
84607
84608     sizeBodyContents: function(width, height) {
84609         var owner = this.owner,
84610             thumbs = owner.thumbs,
84611             length = thumbs.length,
84612             inputEl = owner.inputEl,
84613             innerEl = owner.innerEl,
84614             endEl = owner.endEl,
84615             i = 0;
84616
84617         
84618         for(; i < length; ++i) {
84619             thumbs[i].el.stopAnimation();
84620         }
84621         
84622         if (owner.vertical) {
84623             inputEl.setHeight(height);
84624             innerEl.setHeight(Ext.isNumber(height) ? height - inputEl.getPadding('t') - endEl.getPadding('b') : height);
84625         }
84626         else {
84627             inputEl.setWidth(width);
84628             innerEl.setWidth(Ext.isNumber(width) ? width - inputEl.getPadding('l') - endEl.getPadding('r') : width);
84629         }
84630         owner.syncThumbs();
84631     }
84632 });
84633
84634
84635 Ext.define('Ext.layout.container.Absolute', {
84636
84637     
84638
84639     alias: 'layout.absolute',
84640     extend: 'Ext.layout.container.Anchor',
84641     alternateClassName: 'Ext.layout.AbsoluteLayout',
84642
84643     
84644
84645     itemCls: Ext.baseCSSPrefix + 'abs-layout-item',
84646
84647     type: 'absolute',
84648
84649     onLayout: function() {
84650         var me = this,
84651             target = me.getTarget(),
84652             targetIsBody = target.dom === document.body;
84653
84654         
84655         if (!targetIsBody) {
84656             target.position();
84657         }
84658         me.paddingLeft = target.getPadding('l');
84659         me.paddingTop = target.getPadding('t');
84660         me.callParent(arguments);
84661     },
84662
84663     
84664     adjustWidthAnchor: function(value, comp) {
84665         
84666         return value ? value - comp.getPosition(true)[0] : value;
84667     },
84668
84669     
84670     adjustHeightAnchor: function(value, comp) {
84671         
84672         return value ? value - comp.getPosition(true)[1] : value;
84673     }
84674 });
84675
84676 Ext.define('Ext.layout.container.Accordion', {
84677     extend: 'Ext.layout.container.VBox',
84678     alias: ['layout.accordion'],
84679     alternateClassName: 'Ext.layout.AccordionLayout',
84680
84681     itemCls: Ext.baseCSSPrefix + 'box-item ' + Ext.baseCSSPrefix + 'accordion-item',
84682
84683     align: 'stretch',
84684
84685     
84686     fill : true,
84687
84688     
84689     autoWidth : true,
84690
84691     
84692     titleCollapse : true,
84693
84694     
84695     hideCollapseTool : false,
84696
84697     
84698     collapseFirst : false,
84699
84700     
84701     animate : true,
84702     
84703     activeOnTop : false,
84704     
84705     multi: false,
84706
84707     constructor: function() {
84708         var me = this;
84709
84710         me.callParent(arguments);
84711
84712         
84713         me.initialAnimate = me.animate;
84714         me.animate = false;
84715
84716         
84717         if (me.fill === false) {
84718             me.itemCls = Ext.baseCSSPrefix + 'accordion-item';
84719         }
84720     },
84721
84722     
84723     
84724     beforeLayout: function() {
84725         var me = this;
84726
84727         me.callParent(arguments);
84728         if (me.fill) {
84729             if (!(me.owner.el.dom.style.height || me.getLayoutTargetSize().height)) {
84730                 return false;
84731             }
84732         } else {
84733             me.owner.componentLayout.monitorChildren = false;
84734             me.autoSize = true;
84735             me.owner.setAutoScroll(true);
84736         }
84737     },
84738
84739     renderItems : function(items, target) {
84740         var me = this,
84741             ln = items.length,
84742             i = 0,
84743             comp,
84744             targetSize = me.getLayoutTargetSize(),
84745             renderedPanels = [];
84746
84747         for (; i < ln; i++) {
84748             comp = items[i];
84749             if (!comp.rendered) {
84750                 renderedPanels.push(comp);
84751
84752                 
84753                 if (me.collapseFirst) {
84754                     comp.collapseFirst = me.collapseFirst;
84755                 }
84756                 if (me.hideCollapseTool) {
84757                     comp.hideCollapseTool = me.hideCollapseTool;
84758                     comp.titleCollapse = true;
84759                 }
84760                 else if (me.titleCollapse) {
84761                     comp.titleCollapse = me.titleCollapse;
84762                 }
84763
84764                 delete comp.hideHeader;
84765                 comp.collapsible = true;
84766                 comp.title = comp.title || '&#160;';
84767
84768                 
84769                 comp.width = targetSize.width;
84770                 if (me.fill) {
84771                     delete comp.height;
84772                     delete comp.flex;
84773
84774                     
84775                     if (me.expandedItem !== undefined) {
84776                         comp.collapsed = true;
84777                     }
84778                     
84779                     else if (comp.hasOwnProperty('collapsed') && comp.collapsed === false) {
84780                         comp.flex = 1;
84781                         me.expandedItem = i;
84782                     } else {
84783                         comp.collapsed = true;
84784                     }
84785                     
84786                     me.owner.mon(comp, {
84787                         show: me.onComponentShow,
84788                         beforeexpand: me.onComponentExpand,
84789                         beforecollapse: me.onComponentCollapse,
84790                         scope: me
84791                     });
84792                 } else {
84793                     delete comp.flex;
84794                     comp.animCollapse = me.initialAnimate;
84795                     comp.autoHeight = true;
84796                     comp.autoScroll = false;
84797                 }
84798                 comp.border = comp.collapsed;
84799             }
84800         }
84801
84802         
84803         if (ln && me.expandedItem === undefined) {
84804             me.expandedItem = 0;
84805             comp = items[0];
84806             comp.collapsed = comp.border = false;
84807             if (me.fill) {
84808                 comp.flex = 1;
84809             }
84810         }
84811
84812         
84813         me.callParent(arguments);
84814
84815         
84816         ln = renderedPanels.length;
84817         for (i = 0; i < ln; i++) {
84818             comp = renderedPanels[i];
84819
84820             
84821             delete comp.width;
84822
84823             comp.header.addCls(Ext.baseCSSPrefix + 'accordion-hd');
84824             comp.body.addCls(Ext.baseCSSPrefix + 'accordion-body');
84825         }
84826     },
84827
84828     onLayout: function() {
84829         var me = this;
84830
84831
84832         if (me.fill) {
84833             me.callParent(arguments);
84834         } else {
84835             var targetSize = me.getLayoutTargetSize(),
84836                 items = me.getVisibleItems(),
84837                 len = items.length,
84838                 i = 0, comp;
84839
84840             for (; i < len; i++) {
84841                 comp = items[i];
84842                 if (comp.collapsed) {
84843                     items[i].setWidth(targetSize.width);
84844                 } else {
84845                     items[i].setSize(null, null);
84846                 }
84847             }
84848         }
84849         me.updatePanelClasses();
84850
84851         return me;
84852     },
84853
84854     updatePanelClasses: function() {
84855         var children = this.getLayoutItems(),
84856             ln = children.length,
84857             siblingCollapsed = true,
84858             i, child;
84859
84860         for (i = 0; i < ln; i++) {
84861             child = children[i];
84862
84863             
84864             
84865             if (Ext.isWindows) {
84866                 child.el.dom.scrollTop = 0;
84867             }
84868
84869             if (siblingCollapsed) {
84870                 child.header.removeCls(Ext.baseCSSPrefix + 'accordion-hd-sibling-expanded');
84871             }
84872             else {
84873                 child.header.addCls(Ext.baseCSSPrefix + 'accordion-hd-sibling-expanded');
84874             }
84875
84876             if (i + 1 == ln && child.collapsed) {
84877                 child.header.addCls(Ext.baseCSSPrefix + 'accordion-hd-last-collapsed');
84878             }
84879             else {
84880                 child.header.removeCls(Ext.baseCSSPrefix + 'accordion-hd-last-collapsed');
84881             }
84882             siblingCollapsed = child.collapsed;
84883         }
84884     },
84885     
84886     animCallback: function(){
84887         Ext.Array.forEach(this.toCollapse, function(comp){
84888             comp.fireEvent('collapse', comp);
84889         });
84890         
84891         Ext.Array.forEach(this.toExpand, function(comp){
84892             comp.fireEvent('expand', comp);
84893         });    
84894     },
84895     
84896     setupEvents: function(){
84897         this.toCollapse = [];
84898         this.toExpand = [];    
84899     },
84900
84901     
84902     
84903     
84904     onComponentExpand: function(toExpand) {
84905         var me = this,
84906             it = me.owner.items.items,
84907             len = it.length,
84908             i = 0,
84909             comp;
84910
84911         me.setupEvents();
84912         for (; i < len; i++) {
84913             comp = it[i];
84914             if (comp === toExpand && comp.collapsed) {
84915                 me.setExpanded(comp);
84916             } else if (!me.multi && (comp.rendered && comp.header.rendered && comp !== toExpand && !comp.collapsed)) {
84917                 me.setCollapsed(comp);
84918             }
84919         }
84920
84921         me.animate = me.initialAnimate;
84922         if (me.activeOnTop) {
84923             
84924             me.owner.insert(0, toExpand); 
84925         } else {
84926             me.layout();
84927         }
84928         me.animate = false;
84929         return false;
84930     },
84931
84932     onComponentCollapse: function(comp) {
84933         var me = this,
84934             toExpand = comp.next() || comp.prev(),
84935             expanded = me.multi ? me.owner.query('>panel:not([collapsed])') : [];
84936
84937         me.setupEvents();
84938         
84939         
84940         if (me.multi) {
84941             me.setCollapsed(comp);
84942
84943             
84944             
84945             if (expanded.length === 1 && expanded[0] === comp) {
84946                 me.setExpanded(toExpand);
84947             }
84948
84949             me.animate = me.initialAnimate;
84950             me.layout();
84951             me.animate = false;
84952         }
84953         
84954         else if (toExpand) {
84955             me.onComponentExpand(toExpand);
84956         }
84957         return false;
84958     },
84959
84960     onComponentShow: function(comp) {
84961         
84962         this.onComponentExpand(comp);
84963     },
84964
84965     setCollapsed: function(comp) {
84966         var otherDocks = comp.getDockedItems(),
84967             dockItem,
84968             len = otherDocks.length,
84969             i = 0;
84970
84971         
84972         comp.hiddenDocked = [];
84973         for (; i < len; i++) {
84974             dockItem = otherDocks[i];
84975             if ((dockItem !== comp.header) && !dockItem.hidden) {
84976                 dockItem.hidden = true;
84977                 comp.hiddenDocked.push(dockItem);
84978             }
84979         }
84980         comp.addCls(comp.collapsedCls);
84981         comp.header.addCls(comp.collapsedHeaderCls);
84982         comp.height = comp.header.getHeight();
84983         comp.el.setHeight(comp.height);
84984         comp.collapsed = true;
84985         delete comp.flex;
84986         if (this.initialAnimate) {
84987             this.toCollapse.push(comp);
84988         } else {
84989             comp.fireEvent('collapse', comp);
84990         }
84991         if (comp.collapseTool) {
84992             comp.collapseTool.setType('expand-' + comp.getOppositeDirection(comp.collapseDirection));
84993         }
84994     },
84995
84996     setExpanded: function(comp) {
84997         var otherDocks = comp.hiddenDocked,
84998             len = otherDocks ? otherDocks.length : 0,
84999             i = 0;
85000
85001         
85002         for (; i < len; i++) {
85003             otherDocks[i].show();
85004         }
85005
85006         
85007         if (!comp.body.isVisible()) {
85008             comp.body.show();
85009         }
85010         delete comp.collapsed;
85011         delete comp.height;
85012         delete comp.componentLayout.lastComponentSize;
85013         comp.suspendLayout = false;
85014         comp.flex = 1;
85015         comp.removeCls(comp.collapsedCls);
85016         comp.header.removeCls(comp.collapsedHeaderCls);
85017          if (this.initialAnimate) {
85018             this.toExpand.push(comp);
85019         } else {
85020             comp.fireEvent('expand', comp);
85021         }
85022         if (comp.collapseTool) {
85023             comp.collapseTool.setType('collapse-' + comp.collapseDirection);
85024         }
85025         comp.setAutoScroll(comp.initialConfig.autoScroll);
85026     }
85027 });
85028
85029 Ext.define('Ext.resizer.Splitter', {
85030     extend: 'Ext.Component',
85031     requires: ['Ext.XTemplate'],
85032     uses: ['Ext.resizer.SplitterTracker'],
85033     alias: 'widget.splitter',
85034
85035     renderTpl: [
85036         '<tpl if="collapsible===true">',
85037             '<div id="{id}-collapseEl" class="', Ext.baseCSSPrefix, 'collapse-el ',
85038                     Ext.baseCSSPrefix, 'layout-split-{collapseDir}">&nbsp;</div>',
85039         '</tpl>'
85040     ],
85041
85042     baseCls: Ext.baseCSSPrefix + 'splitter',
85043     collapsedClsInternal: Ext.baseCSSPrefix + 'splitter-collapsed',
85044
85045     
85046     collapsible: false,
85047
85048     
85049
85050     
85051     collapseOnDblClick: true,
85052
85053     
85054     defaultSplitMin: 40,
85055
85056     
85057     defaultSplitMax: 1000,
85058
85059     
85060
85061     width: 5,
85062     height: 5,
85063
85064     
85065     collapseTarget: 'next',
85066
85067     
85068
85069     onRender: function() {
85070         var me = this,
85071             target = me.getCollapseTarget(),
85072             collapseDir = me.getCollapseDirection();
85073
85074         Ext.applyIf(me.renderData, {
85075             collapseDir: collapseDir,
85076             collapsible: me.collapsible || target.collapsible
85077         });
85078
85079         me.addChildEls('collapseEl');
85080
85081         this.callParent(arguments);
85082
85083         
85084         if (me.performCollapse !== false) {
85085             if (me.renderData.collapsible) {
85086                 me.mon(me.collapseEl, 'click', me.toggleTargetCmp, me);
85087             }
85088             if (me.collapseOnDblClick) {
85089                 me.mon(me.el, 'dblclick', me.toggleTargetCmp, me);
85090             }
85091         }
85092
85093         
85094         me.mon(target, 'collapse', me.onTargetCollapse, me);
85095         me.mon(target, 'expand', me.onTargetExpand, me);
85096
85097         me.el.addCls(me.baseCls + '-' + me.orientation);
85098         me.el.unselectable();
85099
85100         me.tracker = Ext.create('Ext.resizer.SplitterTracker', {
85101             el: me.el
85102         });
85103
85104         
85105         me.relayEvents(me.tracker, [ 'beforedragstart', 'dragstart', 'dragend' ]);
85106     },
85107
85108     getCollapseDirection: function() {
85109         var me = this,
85110             idx,
85111             type = me.ownerCt.layout.type;
85112
85113         
85114         
85115         
85116         
85117         
85118         
85119         
85120         if (me.collapseTarget.isComponent) {
85121             idx = Number(me.ownerCt.items.indexOf(me.collapseTarget) == me.ownerCt.items.indexOf(me) - 1) << 1 | Number(type == 'hbox');
85122         } else {
85123             idx = Number(me.collapseTarget == 'prev') << 1 | Number(type == 'hbox');
85124         }
85125
85126         
85127         me.orientation = ['horizontal', 'vertical'][idx & 1];
85128         return ['bottom', 'right', 'top', 'left'][idx];
85129     },
85130
85131     getCollapseTarget: function() {
85132         var me = this;
85133
85134         return me.collapseTarget.isComponent ? me.collapseTarget : me.collapseTarget == 'prev' ? me.previousSibling() : me.nextSibling();
85135     },
85136
85137     onTargetCollapse: function(target) {
85138         this.el.addCls([this.collapsedClsInternal, this.collapsedCls]);
85139     },
85140
85141     onTargetExpand: function(target) {
85142         this.el.removeCls([this.collapsedClsInternal, this.collapsedCls]);
85143     },
85144
85145     toggleTargetCmp: function(e, t) {
85146         var cmp = this.getCollapseTarget();
85147
85148         if (cmp.isVisible()) {
85149             
85150             if (cmp.collapsed) {
85151                 cmp.expand(cmp.animCollapse);
85152             
85153             } else {
85154                 cmp.collapse(this.renderData.collapseDir, cmp.animCollapse);
85155             }
85156         }
85157     },
85158
85159     
85160     setSize: function() {
85161         var me = this;
85162         me.callParent(arguments);
85163         if (Ext.isIE) {
85164             me.el.repaint();
85165         }
85166     }
85167 });
85168
85169
85170 Ext.define('Ext.layout.container.Border', {
85171
85172     alias: ['layout.border'],
85173     extend: 'Ext.layout.container.Container',
85174     requires: ['Ext.resizer.Splitter', 'Ext.container.Container', 'Ext.fx.Anim'],
85175     alternateClassName: 'Ext.layout.BorderLayout',
85176
85177     targetCls: Ext.baseCSSPrefix + 'border-layout-ct',
85178
85179     itemCls: Ext.baseCSSPrefix + 'border-item',
85180
85181     bindToOwnerCtContainer: true,
85182
85183     percentageRe: /(\d+)%/,
85184
85185     slideDirection: {
85186         north: 't',
85187         south: 'b',
85188         west: 'l',
85189         east: 'r'
85190     },
85191
85192     constructor: function(config) {
85193         this.initialConfig = config;
85194         this.callParent(arguments);
85195     },
85196
85197     onLayout: function() {
85198         var me = this;
85199         if (!me.borderLayoutInitialized) {
85200             me.initializeBorderLayout();
85201         }
85202
85203         
85204         me.fixHeightConstraints();
85205         me.shadowLayout.onLayout();
85206         if (me.embeddedContainer) {
85207             me.embeddedContainer.layout.onLayout();
85208         }
85209
85210         
85211         
85212         if (!me.initialCollapsedComplete) {
85213             Ext.iterate(me.regions, function(name, region){
85214                 if (region.borderCollapse) {
85215                     me.onBeforeRegionCollapse(region, region.collapseDirection, false, 0);
85216                 }
85217             });
85218             me.initialCollapsedComplete = true;
85219         }
85220     },
85221
85222     isValidParent : function(item, target, position) {
85223         if (!this.borderLayoutInitialized) {
85224             this.initializeBorderLayout();
85225         }
85226
85227         
85228         return this.shadowLayout.isValidParent(item, target, position);
85229     },
85230
85231     beforeLayout: function() {
85232         if (!this.borderLayoutInitialized) {
85233             this.initializeBorderLayout();
85234         }
85235
85236         
85237         this.shadowLayout.beforeLayout();
85238
85239         
85240     },
85241
85242     renderItems: function(items, target) {
85243     },
85244
85245     renderItem: function(item) {
85246     },
85247
85248     renderChildren: function() {
85249         if (!this.borderLayoutInitialized) {
85250             this.initializeBorderLayout();
85251         }
85252
85253         this.shadowLayout.renderChildren();
85254     },
85255
85256     
85257     getVisibleItems: function() {
85258         return Ext.ComponentQuery.query(':not([slideOutAnim])', this.callParent(arguments));
85259     },
85260
85261     initializeBorderLayout: function() {
85262         var me = this,
85263             i = 0,
85264             items = me.getLayoutItems(),
85265             ln = items.length,
85266             regions = (me.regions = {}),
85267             vBoxItems = [],
85268             hBoxItems = [],
85269             horizontalFlex = 0,
85270             verticalFlex = 0,
85271             comp, percentage;
85272
85273         
85274         me.splitters = {};
85275
85276         
85277         for (; i < ln; i++) {
85278             comp = items[i];
85279             regions[comp.region] = comp;
85280
85281             
85282             if (comp.region != 'center' && comp.collapsible && comp.collapseMode != 'header') {
85283
85284                 
85285                 comp.borderCollapse = comp.collapsed;
85286                 comp.collapsed = false;
85287
85288                 comp.on({
85289                     beforecollapse: me.onBeforeRegionCollapse,
85290                     beforeexpand: me.onBeforeRegionExpand,
85291                     destroy: me.onRegionDestroy,
85292                     scope: me
85293                 });
85294                 me.setupState(comp);
85295             }
85296         }
85297         comp = regions.center;
85298         if (!comp.flex) {
85299             comp.flex = 1;
85300         }
85301         delete comp.width;
85302         comp.maintainFlex = true;
85303
85304         
85305         comp = regions.west;
85306         if (comp) {
85307             comp.collapseDirection = Ext.Component.DIRECTION_LEFT;
85308             hBoxItems.push(comp);
85309             if (comp.split) {
85310                 hBoxItems.push(me.splitters.west = me.createSplitter(comp));
85311             }
85312             percentage = Ext.isString(comp.width) && comp.width.match(me.percentageRe);
85313             if (percentage) {
85314                 horizontalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
85315                 delete comp.width;
85316             }
85317         }
85318         comp = regions.north;
85319         if (comp) {
85320             comp.collapseDirection = Ext.Component.DIRECTION_TOP;
85321             vBoxItems.push(comp);
85322             if (comp.split) {
85323                 vBoxItems.push(me.splitters.north = me.createSplitter(comp));
85324             }
85325             percentage = Ext.isString(comp.height) && comp.height.match(me.percentageRe);
85326             if (percentage) {
85327                 verticalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
85328                 delete comp.height;
85329             }
85330         }
85331
85332         
85333         if (regions.north || regions.south) {
85334             if (regions.east || regions.west) {
85335
85336                 
85337                 vBoxItems.push(me.embeddedContainer = Ext.create('Ext.container.Container', {
85338                     xtype: 'container',
85339                     region: 'center',
85340                     id: me.owner.id + '-embedded-center',
85341                     cls: Ext.baseCSSPrefix + 'border-item',
85342                     flex: regions.center.flex,
85343                     maintainFlex: true,
85344                     layout: {
85345                         type: 'hbox',
85346                         align: 'stretch',
85347                         getVisibleItems: me.getVisibleItems
85348                     }
85349                 }));
85350                 hBoxItems.push(regions.center);
85351             }
85352             
85353             else {
85354                 vBoxItems.push(regions.center);
85355             }
85356         }
85357         
85358         else {
85359             hBoxItems.push(regions.center);
85360         }
85361
85362         
85363         comp = regions.south;
85364         if (comp) {
85365             comp.collapseDirection = Ext.Component.DIRECTION_BOTTOM;
85366             if (comp.split) {
85367                 vBoxItems.push(me.splitters.south = me.createSplitter(comp));
85368             }
85369             percentage = Ext.isString(comp.height) && comp.height.match(me.percentageRe);
85370             if (percentage) {
85371                 verticalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
85372                 delete comp.height;
85373             }
85374             vBoxItems.push(comp);
85375         }
85376         comp = regions.east;
85377         if (comp) {
85378             comp.collapseDirection = Ext.Component.DIRECTION_RIGHT;
85379             if (comp.split) {
85380                 hBoxItems.push(me.splitters.east = me.createSplitter(comp));
85381             }
85382             percentage = Ext.isString(comp.width) && comp.width.match(me.percentageRe);
85383             if (percentage) {
85384                 horizontalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
85385                 delete comp.width;
85386             }
85387             hBoxItems.push(comp);
85388         }
85389
85390         
85391         
85392         
85393         
85394         if (regions.north || regions.south) {
85395
85396             me.shadowContainer = Ext.create('Ext.container.Container', {
85397                 ownerCt: me.owner,
85398                 el: me.getTarget(),
85399                 layout: Ext.applyIf({
85400                     type: 'vbox',
85401                     align: 'stretch',
85402                     getVisibleItems: me.getVisibleItems
85403                 }, me.initialConfig)
85404             });
85405             me.createItems(me.shadowContainer, vBoxItems);
85406
85407             
85408             if (me.splitters.north) {
85409                 me.splitters.north.ownerCt = me.shadowContainer;
85410             }
85411             if (me.splitters.south) {
85412                 me.splitters.south.ownerCt = me.shadowContainer;
85413             }
85414
85415             
85416             if (me.embeddedContainer) {
85417                 me.embeddedContainer.ownerCt = me.shadowContainer;
85418                 me.createItems(me.embeddedContainer, hBoxItems);
85419
85420                 
85421                 if (me.splitters.east) {
85422                     me.splitters.east.ownerCt = me.embeddedContainer;
85423                 }
85424                 if (me.splitters.west) {
85425                     me.splitters.west.ownerCt = me.embeddedContainer;
85426                 }
85427
85428                 
85429                 
85430                 
85431                 
85432                 
85433                 Ext.each([me.splitters.north, me.splitters.south], function (splitter) {
85434                     if (splitter) {
85435                         splitter.on('beforedragstart', me.fixHeightConstraints, me);
85436                     }
85437                 });
85438
85439                 
85440                 if (horizontalFlex) {
85441                     regions.center.flex -= horizontalFlex;
85442                 }
85443                 
85444                 if (verticalFlex) {
85445                     me.embeddedContainer.flex -= verticalFlex;
85446                 }
85447             } else {
85448                 
85449                 if (verticalFlex) {
85450                     regions.center.flex -= verticalFlex;
85451                 }
85452             }
85453         }
85454         
85455         
85456         else {
85457             me.shadowContainer = Ext.create('Ext.container.Container', {
85458                 ownerCt: me.owner,
85459                 el: me.getTarget(),
85460                 layout: Ext.applyIf({
85461                     type: (hBoxItems.length == 1) ? 'fit' : 'hbox',
85462                     align: 'stretch'
85463                 }, me.initialConfig)
85464             });
85465             me.createItems(me.shadowContainer, hBoxItems);
85466
85467             
85468             if (me.splitters.east) {
85469                 me.splitters.east.ownerCt = me.shadowContainer;
85470             }
85471             if (me.splitters.west) {
85472                 me.splitters.west.ownerCt = me.shadowContainer;
85473             }
85474
85475             
85476             if (horizontalFlex) {
85477                 regions.center.flex -= verticalFlex;
85478             }
85479         }
85480
85481         
85482         for (i = 0, items = me.shadowContainer.items.items, ln = items.length; i < ln; i++) {
85483             items[i].shadowOwnerCt = me.shadowContainer;
85484         }
85485         if (me.embeddedContainer) {
85486             for (i = 0, items = me.embeddedContainer.items.items, ln = items.length; i < ln; i++) {
85487                 items[i].shadowOwnerCt = me.embeddedContainer;
85488             }
85489         }
85490
85491         
85492         me.shadowLayout = me.shadowContainer.getLayout();
85493
85494         me.borderLayoutInitialized = true;
85495     },
85496
85497     setupState: function(comp){
85498         var getState = comp.getState;
85499         comp.getState = function(){
85500             
85501             var state = getState.call(comp) || {},
85502                 region = comp.region;
85503
85504             state.collapsed = !!comp.collapsed;
85505             if (region == 'west' || region == 'east') {
85506                 state.width = comp.getWidth();
85507             } else {
85508                 state.height = comp.getHeight();
85509             }
85510             return state;
85511         };
85512         comp.addStateEvents(['collapse', 'expand', 'resize']);
85513     },
85514
85515     
85516     createItems: function(container, items){
85517         
85518         
85519         delete container.items;
85520         container.initItems();
85521         container.items.addAll(items);
85522     },
85523
85524     
85525     
85526     createSplitter: function(comp) {
85527         var me = this,
85528             interceptCollapse = (comp.collapseMode != 'header'),
85529             resizer;
85530
85531         resizer = Ext.create('Ext.resizer.Splitter', {
85532             hidden: !!comp.hidden,
85533             collapseTarget: comp,
85534             performCollapse: !interceptCollapse,
85535             listeners: interceptCollapse ? {
85536                 click: {
85537                     fn: Ext.Function.bind(me.onSplitterCollapseClick, me, [comp]),
85538                     element: 'collapseEl'
85539                 }
85540             } : null
85541         });
85542
85543         
85544         if (comp.collapseMode == 'mini') {
85545             comp.placeholder = resizer;
85546             resizer.collapsedCls = comp.collapsedCls;
85547         }
85548
85549         
85550         comp.on({
85551             hide: me.onRegionVisibilityChange,
85552             show: me.onRegionVisibilityChange,
85553             scope: me
85554         });
85555         return resizer;
85556     },
85557
85558     
85559     
85560     fixHeightConstraints: function () {
85561         var me = this,
85562             ct = me.embeddedContainer,
85563             maxHeight = 1e99, minHeight = -1;
85564
85565         if (!ct) {
85566             return;
85567         }
85568
85569         ct.items.each(function (item) {
85570             if (Ext.isNumber(item.maxHeight)) {
85571                 maxHeight = Math.max(maxHeight, item.maxHeight);
85572             }
85573             if (Ext.isNumber(item.minHeight)) {
85574                 minHeight = Math.max(minHeight, item.minHeight);
85575             }
85576         });
85577
85578         ct.maxHeight = maxHeight;
85579         ct.minHeight = minHeight;
85580     },
85581
85582     
85583     onRegionVisibilityChange: function(comp){
85584         this.splitters[comp.region][comp.hidden ? 'hide' : 'show']();
85585         this.layout();
85586     },
85587
85588     
85589     
85590     
85591     onSplitterCollapseClick: function(comp) {
85592         if (comp.collapsed) {
85593             this.onPlaceHolderToolClick(null, null, null, {client: comp});
85594         } else {
85595             comp.collapse();
85596         }
85597     },
85598
85599     
85600     getPlaceholder: function(comp) {
85601         var me = this,
85602             placeholder = comp.placeholder,
85603             shadowContainer = comp.shadowOwnerCt,
85604             shadowLayout = shadowContainer.layout,
85605             oppositeDirection = Ext.panel.Panel.prototype.getOppositeDirection(comp.collapseDirection),
85606             horiz = (comp.region == 'north' || comp.region == 'south');
85607
85608         
85609         if (comp.collapseMode == 'header') {
85610             return;
85611         }
85612
85613         
85614         if (!placeholder) {
85615             if (comp.collapseMode == 'mini') {
85616                 placeholder = Ext.create('Ext.resizer.Splitter', {
85617                     id: 'collapse-placeholder-' + comp.id,
85618                     collapseTarget: comp,
85619                     performCollapse: false,
85620                     listeners: {
85621                         click: {
85622                             fn: Ext.Function.bind(me.onSplitterCollapseClick, me, [comp]),
85623                             element: 'collapseEl'
85624                         }
85625                     }
85626                 });
85627                 placeholder.addCls(placeholder.collapsedCls);
85628             } else {
85629                 placeholder = {
85630                     id: 'collapse-placeholder-' + comp.id,
85631                     margins: comp.initialConfig.margins || Ext.getClass(comp).prototype.margins,
85632                     xtype: 'header',
85633                     orientation: horiz ? 'horizontal' : 'vertical',
85634                     title: comp.title,
85635                     textCls: comp.headerTextCls,
85636                     iconCls: comp.iconCls,
85637                     baseCls: comp.baseCls + '-header',
85638                     ui: comp.ui,
85639                     indicateDrag: comp.draggable,
85640                     cls: Ext.baseCSSPrefix + 'region-collapsed-placeholder ' + Ext.baseCSSPrefix + 'region-collapsed-' + comp.collapseDirection + '-placeholder ' + comp.collapsedCls,
85641                     listeners: comp.floatable ? {
85642                         click: {
85643                             fn: function(e) {
85644                                 me.floatCollapsedPanel(e, comp);
85645                             },
85646                             element: 'el'
85647                         }
85648                     } : null
85649                 };
85650                 
85651                 if ((Ext.isIE6 || Ext.isIE7 || (Ext.isIEQuirks)) && !horiz) {
85652                     placeholder.width = 25;
85653                 }
85654                 if (!comp.hideCollapseTool) {
85655                     placeholder[horiz ? 'tools' : 'items'] = [{
85656                         xtype: 'tool',
85657                         client: comp,
85658                         type: 'expand-' + oppositeDirection,
85659                         handler: me.onPlaceHolderToolClick,
85660                         scope: me
85661                     }];
85662                 }
85663             }
85664             placeholder = me.owner.createComponent(placeholder);
85665             if (comp.isXType('panel')) {
85666                 comp.on({
85667                     titlechange: me.onRegionTitleChange,
85668                     iconchange: me.onRegionIconChange,
85669                     scope: me
85670                 });
85671             }
85672         }
85673
85674         
85675         comp.placeholder = placeholder;
85676         placeholder.comp = comp;
85677
85678         return placeholder;
85679     },
85680
85681     
85682     onRegionTitleChange: function(comp, newTitle) {
85683         comp.placeholder.setTitle(newTitle);
85684     },
85685
85686     
85687     onRegionIconChange: function(comp, newIconCls) {
85688         comp.placeholder.setIconCls(newIconCls);
85689     },
85690
85691     
85692     calculateChildBox: function(comp) {
85693         var me = this;
85694         if (me.shadowContainer.items.contains(comp)) {
85695             return me.shadowContainer.layout.calculateChildBox(comp);
85696         }
85697         else if (me.embeddedContainer && me.embeddedContainer.items.contains(comp)) {
85698             return me.embeddedContainer.layout.calculateChildBox(comp);
85699         }
85700     },
85701
85702     
85703     onBeforeRegionCollapse: function(comp, direction, animate) {
85704         if (comp.collapsedChangingLayout) {
85705             return false;
85706         }
85707         comp.collapsedChangingLayout = true;
85708         var me = this,
85709             compEl = comp.el,
85710             width,
85711             miniCollapse = comp.collapseMode == 'mini',
85712             shadowContainer = comp.shadowOwnerCt,
85713             shadowLayout = shadowContainer.layout,
85714             placeholder = comp.placeholder,
85715             sl = me.owner.suspendLayout,
85716             scsl = shadowContainer.suspendLayout,
85717             isNorthOrWest = (comp.region == 'north' || comp.region == 'west'); 
85718
85719         
85720         me.owner.suspendLayout = true;
85721         shadowContainer.suspendLayout = true;
85722
85723         
85724         shadowLayout.layoutBusy = true;
85725         if (shadowContainer.componentLayout) {
85726             shadowContainer.componentLayout.layoutBusy = true;
85727         }
85728         me.shadowContainer.layout.layoutBusy = true;
85729         me.layoutBusy = true;
85730         me.owner.componentLayout.layoutBusy = true;
85731
85732         
85733         if (!placeholder) {
85734             placeholder = me.getPlaceholder(comp);
85735         }
85736
85737         
85738         if (placeholder.shadowOwnerCt === shadowContainer) {
85739             placeholder.show();
85740         }
85741         
85742         
85743         
85744         else {
85745             shadowContainer.insert(shadowContainer.items.indexOf(comp) + (isNorthOrWest ? 0 : 1), placeholder);
85746             placeholder.shadowOwnerCt = shadowContainer;
85747             placeholder.ownerCt = me.owner;
85748         }
85749
85750         
85751         
85752         
85753         comp.hidden = true;
85754
85755         if (!placeholder.rendered) {
85756             shadowLayout.renderItem(placeholder, shadowLayout.innerCt);
85757
85758             
85759             
85760             
85761             
85762             
85763             if (comp.region == 'north' || comp.region == 'south') {
85764                 placeholder.setCalculatedSize(comp.getWidth());
85765             } else {
85766                 placeholder.setCalculatedSize(undefined, comp.getHeight());
85767             }
85768         }
85769
85770         
85771         function afterCollapse() {
85772             
85773             me.owner.suspendLayout = sl;
85774             shadowContainer.suspendLayout = scsl;
85775             delete shadowLayout.layoutBusy;
85776             if (shadowContainer.componentLayout) {
85777                 delete shadowContainer.componentLayout.layoutBusy;
85778             }
85779             delete me.shadowContainer.layout.layoutBusy;
85780             delete me.layoutBusy;
85781             delete me.owner.componentLayout.layoutBusy;
85782             delete comp.collapsedChangingLayout;
85783
85784             
85785             comp.collapsed = true;
85786             comp.fireEvent('collapse', comp);
85787         }
85788
85789         
85790         if (comp.animCollapse && me.initialCollapsedComplete) {
85791             shadowLayout.layout();
85792             compEl.dom.style.zIndex = 100;
85793
85794             
85795             if (!miniCollapse) {
85796                 placeholder.el.hide();
85797             }
85798             compEl.slideOut(me.slideDirection[comp.region], {
85799                 duration: Ext.Number.from(comp.animCollapse, Ext.fx.Anim.prototype.duration),
85800                 listeners: {
85801                     afteranimate: function() {
85802                         compEl.show().setLeftTop(-10000, -10000);
85803                         compEl.dom.style.zIndex = '';
85804
85805                         
85806                        if (!miniCollapse) {
85807                             placeholder.el.slideIn(me.slideDirection[comp.region], {
85808                                 easing: 'linear',
85809                                 duration: 100
85810                             });
85811                         }
85812                         afterCollapse();
85813                     }
85814                 }
85815             });
85816         } else {
85817             compEl.setLeftTop(-10000, -10000);
85818             shadowLayout.layout();
85819             afterCollapse();
85820         }
85821
85822         return false;
85823     },
85824
85825     
85826     onBeforeRegionExpand: function(comp, animate) {
85827         
85828         this.onPlaceHolderToolClick(null, null, null, {client: comp, shouldFireBeforeexpand: false});
85829         return false;
85830     },
85831
85832     
85833     onPlaceHolderToolClick: function(e, target, owner, tool) {
85834         var me = this,
85835             comp = tool.client,
85836
85837             
85838             hidePlaceholder = (comp.collapseMode != 'mini') || !comp.split,
85839             compEl = comp.el,
85840             toCompBox,
85841             placeholder = comp.placeholder,
85842             placeholderEl = placeholder.el,
85843             shadowContainer = comp.shadowOwnerCt,
85844             shadowLayout = shadowContainer.layout,
85845             curSize,
85846             sl = me.owner.suspendLayout,
85847             scsl = shadowContainer.suspendLayout,
85848             isFloating;
85849
85850         if (comp.collapsedChangingLayout) {
85851             return false;
85852         }
85853         if (tool.shouldFireBeforeexpand !== false && comp.fireEvent('beforeexpand', comp, true) === false) {
85854             return false;
85855         }
85856         comp.collapsedChangingLayout = true;
85857         
85858         
85859         
85860         if (comp.getActiveAnimation()) {
85861             comp.stopAnimation();
85862         }
85863
85864         
85865         
85866         
85867         if (comp.slideOutAnim) {
85868             
85869             compEl.un(comp.panelMouseMon);
85870             placeholderEl.un(comp.placeholderMouseMon);
85871
85872             delete comp.slideOutAnim;
85873             delete comp.panelMouseMon;
85874             delete comp.placeholderMouseMon;
85875
85876             
85877             isFloating = true;
85878         }
85879
85880         
85881         me.owner.suspendLayout = true;
85882         shadowContainer.suspendLayout = true;
85883
85884         
85885         shadowLayout.layoutBusy = true;
85886         if (shadowContainer.componentLayout) {
85887             shadowContainer.componentLayout.layoutBusy = true;
85888         }
85889         me.shadowContainer.layout.layoutBusy = true;
85890         me.layoutBusy = true;
85891         me.owner.componentLayout.layoutBusy = true;
85892
85893         
85894         
85895         comp.hidden = false;
85896         comp.collapsed = false;
85897         if (hidePlaceholder) {
85898             placeholder.hidden = true;
85899         }
85900         toCompBox = shadowLayout.calculateChildBox(comp);
85901
85902         
85903         if (comp.collapseTool) {
85904             comp.collapseTool.show();
85905         }
85906
85907         
85908         if (comp.animCollapse && !isFloating) {
85909             compEl.setStyle('visibility', 'hidden');
85910         }
85911         compEl.setLeftTop(toCompBox.left, toCompBox.top);
85912
85913         
85914         
85915         curSize = comp.getSize();
85916         if (curSize.height != toCompBox.height || curSize.width != toCompBox.width) {
85917             me.setItemSize(comp, toCompBox.width, toCompBox.height);
85918         }
85919
85920         
85921         function afterExpand() {
85922             
85923             me.owner.suspendLayout = sl;
85924             shadowContainer.suspendLayout = scsl;
85925             delete shadowLayout.layoutBusy;
85926             if (shadowContainer.componentLayout) {
85927                 delete shadowContainer.componentLayout.layoutBusy;
85928             }
85929             delete me.shadowContainer.layout.layoutBusy;
85930             delete me.layoutBusy;
85931             delete me.owner.componentLayout.layoutBusy;
85932             delete comp.collapsedChangingLayout;
85933
85934             
85935             comp.removeCls(Ext.baseCSSPrefix + 'border-region-slide-in');
85936
85937             
85938             comp.fireEvent('expand', comp);
85939         }
85940
85941         
85942         if (hidePlaceholder) {
85943             placeholder.el.hide();
85944         }
85945
85946         
85947         
85948         if (comp.animCollapse && !isFloating) {
85949             compEl.dom.style.zIndex = 100;
85950             compEl.slideIn(me.slideDirection[comp.region], {
85951                 duration: Ext.Number.from(comp.animCollapse, Ext.fx.Anim.prototype.duration),
85952                 listeners: {
85953                     afteranimate: function() {
85954                         compEl.dom.style.zIndex = '';
85955                         comp.hidden = false;
85956                         shadowLayout.onLayout();
85957                         afterExpand();
85958                     }
85959                 }
85960             });
85961         } else {
85962             shadowLayout.onLayout();
85963             afterExpand();
85964         }
85965     },
85966
85967     floatCollapsedPanel: function(e, comp) {
85968
85969         if (comp.floatable === false) {
85970             return;
85971         }
85972
85973         var me = this,
85974             compEl = comp.el,
85975             placeholder = comp.placeholder,
85976             placeholderEl = placeholder.el,
85977             shadowContainer = comp.shadowOwnerCt,
85978             shadowLayout = shadowContainer.layout,
85979             placeholderBox = shadowLayout.getChildBox(placeholder),
85980             scsl = shadowContainer.suspendLayout,
85981             curSize, toCompBox, compAnim;
85982
85983         
85984         if (e.getTarget('.' + Ext.baseCSSPrefix + 'tool')) {
85985             return;
85986         }
85987
85988         
85989         
85990         if (compEl.getActiveAnimation()) {
85991             return;
85992         }
85993
85994         
85995         
85996         if (comp.slideOutAnim) {
85997             me.slideOutFloatedComponent(comp);
85998             return;
85999         }
86000
86001         
86002         
86003         function onMouseLeaveFloated(e) {
86004             var slideRegion = compEl.getRegion().union(placeholderEl.getRegion()).adjust(1, -1, -1, 1);
86005
86006             
86007             if (!slideRegion.contains(e.getPoint())) {
86008                 me.slideOutFloatedComponent(comp);
86009             }
86010         }
86011
86012         
86013         comp.placeholderMouseMon = placeholderEl.monitorMouseLeave(500, onMouseLeaveFloated);
86014
86015         
86016         shadowContainer.suspendLayout = true;
86017
86018         
86019         me.layoutBusy = true;
86020         me.owner.componentLayout.layoutBusy = true;
86021
86022         
86023         
86024         if (comp.collapseTool) {
86025             comp.collapseTool.hide();
86026         }
86027
86028         
86029         comp.hidden = false;
86030         comp.collapsed = false;
86031         placeholder.hidden = true;
86032
86033         
86034         toCompBox = shadowLayout.calculateChildBox(comp);
86035         placeholder.hidden = false;
86036
86037         
86038         if (comp.region == 'north' || comp.region == 'west') {
86039             toCompBox[shadowLayout.parallelBefore] += placeholderBox[shadowLayout.parallelPrefix] - 1;
86040         } else {
86041             toCompBox[shadowLayout.parallelBefore] -= (placeholderBox[shadowLayout.parallelPrefix] - 1);
86042         }
86043         compEl.setStyle('visibility', 'hidden');
86044         compEl.setLeftTop(toCompBox.left, toCompBox.top);
86045
86046         
86047         
86048         curSize = comp.getSize();
86049         if (curSize.height != toCompBox.height || curSize.width != toCompBox.width) {
86050             me.setItemSize(comp, toCompBox.width, toCompBox.height);
86051         }
86052
86053         
86054         compAnim = {
86055             listeners: {
86056                 afteranimate: function() {
86057                     shadowContainer.suspendLayout = scsl;
86058                     delete me.layoutBusy;
86059                     delete me.owner.componentLayout.layoutBusy;
86060
86061                     
86062                     compAnim.listeners = {
86063                         afterAnimate: function() {
86064                             compEl.show().removeCls(Ext.baseCSSPrefix + 'border-region-slide-in').setLeftTop(-10000, -10000);
86065
86066                             
86067                             comp.hidden = true;
86068                             comp.collapsed = true;
86069                             delete comp.slideOutAnim;
86070                             delete comp.panelMouseMon;
86071                             delete comp.placeholderMouseMon;
86072                         }
86073                     };
86074                     comp.slideOutAnim = compAnim;
86075                 }
86076             },
86077             duration: 500
86078         };
86079
86080         
86081         compEl.addCls(Ext.baseCSSPrefix + 'border-region-slide-in');
86082
86083         
86084         compEl.slideIn(me.slideDirection[comp.region], compAnim);
86085
86086         
86087         comp.panelMouseMon = compEl.monitorMouseLeave(500, onMouseLeaveFloated);
86088
86089     },
86090
86091     slideOutFloatedComponent: function(comp) {
86092         var compEl = comp.el,
86093             slideOutAnim;
86094
86095         
86096         compEl.un(comp.panelMouseMon);
86097         comp.placeholder.el.un(comp.placeholderMouseMon);
86098
86099         
86100         compEl.slideOut(this.slideDirection[comp.region], comp.slideOutAnim);
86101
86102         delete comp.slideOutAnim;
86103         delete comp.panelMouseMon;
86104         delete comp.placeholderMouseMon;
86105     },
86106
86107     
86108     onRegionDestroy: function(comp) {
86109         var placeholder = comp.placeholder;
86110         if (placeholder) {
86111             delete placeholder.ownerCt;
86112             placeholder.destroy();
86113         }
86114     },
86115
86116     
86117     onDestroy: function() {
86118         var me = this,
86119             shadowContainer = me.shadowContainer,
86120             embeddedContainer = me.embeddedContainer;
86121
86122         if (shadowContainer) {
86123             delete shadowContainer.ownerCt;
86124             Ext.destroy(shadowContainer);
86125         }
86126
86127         if (embeddedContainer) {
86128             delete embeddedContainer.ownerCt;
86129             Ext.destroy(embeddedContainer);
86130         }
86131         delete me.regions;
86132         delete me.splitters;
86133         delete me.shadowContainer;
86134         delete me.embeddedContainer;
86135         me.callParent(arguments);
86136     }
86137 });
86138
86139
86140 Ext.define('Ext.layout.container.Card', {
86141
86142     
86143
86144     alias: ['layout.card'],
86145     alternateClassName: 'Ext.layout.CardLayout',
86146
86147     extend: 'Ext.layout.container.AbstractCard',
86148
86149     
86150
86151     
86152     setActiveItem: function(newCard) {
86153         var me = this,
86154             owner = me.owner,
86155             oldCard = me.activeItem,
86156             newIndex;
86157
86158         newCard = me.parseActiveItem(newCard);
86159         newIndex = owner.items.indexOf(newCard);
86160
86161         
86162         if (newIndex == -1) {
86163             newIndex = owner.items.items.length;
86164             owner.add(newCard);
86165         }
86166
86167         
86168         if (newCard && oldCard != newCard) {
86169             
86170             if (!newCard.rendered) {
86171                 me.renderItem(newCard, me.getRenderTarget(), owner.items.length);
86172                 me.configureItem(newCard, 0);
86173             }
86174
86175             me.activeItem = newCard;
86176
86177             
86178             if (newCard.fireEvent('beforeactivate', newCard, oldCard) === false) {
86179                 return false;
86180             }
86181             if (oldCard && oldCard.fireEvent('beforedeactivate', oldCard, newCard) === false) {
86182                 return false;
86183             }
86184
86185             
86186             if (me.sizeAllCards) {
86187                 
86188                 me.onLayout();
86189             }
86190             else {
86191                 me.setItemBox(newCard, me.getTargetBox());
86192             }
86193
86194             me.owner.suspendLayout = true;
86195
86196             if (oldCard) {
86197                 if (me.hideInactive) {
86198                     oldCard.hide();
86199                 }
86200                 oldCard.fireEvent('deactivate', oldCard, newCard);
86201             }
86202
86203             
86204             me.owner.suspendLayout = false;
86205             if (newCard.hidden) {
86206                 newCard.show();
86207             } else {
86208                 me.onLayout();
86209             }
86210
86211             newCard.fireEvent('activate', newCard, oldCard);
86212
86213             return newCard;
86214         }
86215         return false;
86216     },
86217
86218     configureItem: function(item) {
86219         
86220         
86221         item.layoutManagedHeight = 0;
86222         item.layoutManagedWidth = 0;
86223
86224         this.callParent(arguments);
86225     }});
86226
86227 Ext.define('Ext.layout.container.Column', {
86228
86229     extend: 'Ext.layout.container.Auto',
86230     alias: ['layout.column'],
86231     alternateClassName: 'Ext.layout.ColumnLayout',
86232
86233     type: 'column',
86234
86235     itemCls: Ext.baseCSSPrefix + 'column',
86236
86237     targetCls: Ext.baseCSSPrefix + 'column-layout-ct',
86238
86239     scrollOffset: 0,
86240
86241     bindToOwnerCtComponent: false,
86242
86243     getRenderTarget : function() {
86244         if (!this.innerCt) {
86245
86246             
86247             
86248             this.innerCt = this.getTarget().createChild({
86249                 cls: Ext.baseCSSPrefix + 'column-inner'
86250             });
86251
86252             
86253             
86254             
86255             this.clearEl = this.innerCt.createChild({
86256                 cls: Ext.baseCSSPrefix + 'clear',
86257                 role: 'presentation'
86258             });
86259         }
86260         return this.innerCt;
86261     },
86262
86263     
86264     onLayout : function() {
86265         var me = this,
86266             target = me.getTarget(),
86267             items = me.getLayoutItems(),
86268             len = items.length,
86269             item,
86270             i,
86271             parallelMargins = [],
86272             itemParallelMargins,
86273             size,
86274             availableWidth,
86275             columnWidth;
86276
86277         size = me.getLayoutTargetSize();
86278         if (size.width < len * 10) { 
86279             return;
86280         }
86281
86282         
86283         
86284         
86285         if (me.adjustmentPass) {
86286             if (Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks) {
86287                 size.width = me.adjustedWidth;
86288             }
86289         } else {
86290             i = target.getStyle('overflow');
86291             if (i && i != 'hidden') {
86292                 me.autoScroll = true;
86293                 if (!(Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks)) {
86294                     target.setStyle('overflow', 'hidden');
86295                     size = me.getLayoutTargetSize();
86296                 }
86297             }
86298         }
86299
86300         availableWidth = size.width - me.scrollOffset;
86301         me.innerCt.setWidth(availableWidth);
86302
86303         
86304         
86305         for (i = 0; i < len; i++) {
86306             item = items[i];
86307             itemParallelMargins = parallelMargins[i] = item.getEl().getMargin('lr');
86308             if (!item.columnWidth) {
86309                 availableWidth -= (item.getWidth() + itemParallelMargins);
86310             }
86311         }
86312
86313         availableWidth = availableWidth < 0 ? 0 : availableWidth;
86314         for (i = 0; i < len; i++) {
86315             item = items[i];
86316             if (item.columnWidth) {
86317                 columnWidth = Math.floor(item.columnWidth * availableWidth) - parallelMargins[i];
86318                 me.setItemSize(item, columnWidth, item.height);
86319             } else {
86320                 me.layoutItem(item);
86321             }
86322         }
86323
86324         
86325         if (!me.adjustmentPass && me.autoScroll) {
86326
86327             
86328             target.setStyle('overflow', 'auto');
86329             me.adjustmentPass = (target.dom.scrollHeight > size.height);
86330             if (Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks) {
86331                 me.adjustedWidth = size.width - Ext.getScrollBarWidth();
86332             } else {
86333                 target.setStyle('overflow', 'auto');
86334             }
86335
86336             
86337             if (me.adjustmentPass) {
86338                 me.onLayout();
86339             }
86340         }
86341         delete me.adjustmentPass;
86342     },
86343
86344     configureItem: function(item) {
86345         this.callParent(arguments);
86346
86347         if (item.columnWidth) {
86348             item.layoutManagedWidth = 1;
86349         }
86350     }
86351 });
86352
86353 Ext.define('Ext.layout.container.Table', {
86354
86355     
86356
86357     alias: ['layout.table'],
86358     extend: 'Ext.layout.container.Auto',
86359     alternateClassName: 'Ext.layout.TableLayout',
86360
86361     
86362
86363     
86364
86365     
86366     monitorResize:false,
86367
86368     type: 'table',
86369
86370     
86371     
86372     autoSize: true,
86373
86374     clearEl: true, 
86375
86376     targetCls: Ext.baseCSSPrefix + 'table-layout-ct',
86377     tableCls: Ext.baseCSSPrefix + 'table-layout',
86378     cellCls: Ext.baseCSSPrefix + 'table-layout-cell',
86379
86380     
86381     tableAttrs:null,
86382
86383     
86384
86385     
86386
86387     
86388     renderItems: function(items) {
86389         var tbody = this.getTable().tBodies[0],
86390             rows = tbody.rows,
86391             i = 0,
86392             len = items.length,
86393             cells, curCell, rowIdx, cellIdx, item, trEl, tdEl, itemCt;
86394
86395         
86396         cells = this.calculateCells(items);
86397
86398         
86399         
86400         
86401         for (; i < len; i++) {
86402             curCell = cells[i];
86403             rowIdx = curCell.rowIdx;
86404             cellIdx = curCell.cellIdx;
86405             item = items[i];
86406
86407             
86408             trEl = rows[rowIdx];
86409             if (!trEl) {
86410                 trEl = tbody.insertRow(rowIdx);
86411                 if (this.trAttrs) {
86412                     trEl.set(this.trAttrs);
86413                 }
86414             }
86415
86416             
86417             itemCt = tdEl = Ext.get(trEl.cells[cellIdx] || trEl.insertCell(cellIdx));
86418             if (this.needsDivWrap()) { 
86419                 itemCt = tdEl.first() || tdEl.createChild({tag: 'div'});
86420                 itemCt.setWidth(null);
86421             }
86422
86423             
86424             if (!item.rendered) {
86425                 this.renderItem(item, itemCt, 0);
86426             }
86427             else if (!this.isValidParent(item, itemCt, 0)) {
86428                 this.moveItem(item, itemCt, 0);
86429             }
86430
86431             
86432             if (this.tdAttrs) {
86433                 tdEl.set(this.tdAttrs);
86434             }
86435             tdEl.set({
86436                 colSpan: item.colspan || 1,
86437                 rowSpan: item.rowspan || 1,
86438                 id: item.cellId || '',
86439                 cls: this.cellCls + ' ' + (item.cellCls || '')
86440             });
86441
86442             
86443             if (!cells[i + 1] || cells[i + 1].rowIdx !== rowIdx) {
86444                 cellIdx++;
86445                 while (trEl.cells[cellIdx]) {
86446                     trEl.deleteCell(cellIdx);
86447                 }
86448             }
86449         }
86450
86451         
86452         rowIdx++;
86453         while (tbody.rows[rowIdx]) {
86454             tbody.deleteRow(rowIdx);
86455         }
86456     },
86457
86458     afterLayout: function() {
86459         this.callParent();
86460
86461         if (this.needsDivWrap()) {
86462             
86463             Ext.Array.forEach(this.getLayoutItems(), function(item) {
86464                 Ext.fly(item.el.dom.parentNode).setWidth(item.getWidth());
86465             });
86466         }
86467     },
86468
86469     
86470     calculateCells: function(items) {
86471         var cells = [],
86472             rowIdx = 0,
86473             colIdx = 0,
86474             cellIdx = 0,
86475             totalCols = this.columns || Infinity,
86476             rowspans = [], 
86477             i = 0, j,
86478             len = items.length,
86479             item;
86480
86481         for (; i < len; i++) {
86482             item = items[i];
86483
86484             
86485             while (colIdx >= totalCols || rowspans[colIdx] > 0) {
86486                 if (colIdx >= totalCols) {
86487                     
86488                     colIdx = 0;
86489                     cellIdx = 0;
86490                     rowIdx++;
86491
86492                     
86493                     for (j = 0; j < totalCols; j++) {
86494                         if (rowspans[j] > 0) {
86495                             rowspans[j]--;
86496                         }
86497                     }
86498                 } else {
86499                     colIdx++;
86500                 }
86501             }
86502
86503             
86504             cells.push({
86505                 rowIdx: rowIdx,
86506                 cellIdx: cellIdx
86507             });
86508
86509             
86510             for (j = item.colspan || 1; j; --j) {
86511                 rowspans[colIdx] = item.rowspan || 1;
86512                 ++colIdx;
86513             }
86514             ++cellIdx;
86515         }
86516
86517         return cells;
86518     },
86519
86520     
86521     getTable: function() {
86522         var table = this.table;
86523         if (!table) {
86524             table = this.table = this.getTarget().createChild(
86525                 Ext.apply({
86526                     tag: 'table',
86527                     role: 'presentation',
86528                     cls: this.tableCls,
86529                     cellspacing: 0, 
86530                     cn: {tag: 'tbody'}
86531                 }, this.tableAttrs),
86532                 null, true
86533             );
86534         }
86535         return table;
86536     },
86537
86538     
86539     needsDivWrap: function() {
86540         return Ext.isOpera10_5;
86541     }
86542 });
86543
86544 Ext.define('Ext.menu.Item', {
86545     extend: 'Ext.Component',
86546     alias: 'widget.menuitem',
86547     alternateClassName: 'Ext.menu.TextItem',
86548
86549     
86550
86551     
86552
86553     
86554     activeCls: Ext.baseCSSPrefix + 'menu-item-active',
86555
86556     
86557     ariaRole: 'menuitem',
86558
86559     
86560     canActivate: true,
86561
86562     
86563     clickHideDelay: 1,
86564
86565     
86566     destroyMenu: true,
86567
86568     
86569     disabledCls: Ext.baseCSSPrefix + 'menu-item-disabled',
86570
86571     
86572
86573      
86574
86575     
86576     hideOnClick: true,
86577
86578     
86579
86580     
86581
86582     isMenuItem: true,
86583
86584     
86585
86586     
86587     menuAlign: 'tl-tr?',
86588
86589     
86590     menuExpandDelay: 200,
86591
86592     
86593     menuHideDelay: 200,
86594
86595     
86596
86597     renderTpl: [
86598         '<tpl if="plain">',
86599             '{text}',
86600         '</tpl>',
86601         '<tpl if="!plain">',
86602             '<a id="{id}-itemEl" class="' + Ext.baseCSSPrefix + 'menu-item-link" href="{href}" <tpl if="hrefTarget">target="{hrefTarget}"</tpl> hidefocus="true" unselectable="on">',
86603                 '<img id="{id}-iconEl" src="{icon}" class="' + Ext.baseCSSPrefix + 'menu-item-icon {iconCls}" />',
86604                 '<span id="{id}-textEl" class="' + Ext.baseCSSPrefix + 'menu-item-text" <tpl if="menu">style="margin-right: 17px;"</tpl> >{text}</span>',
86605                 '<tpl if="menu">',
86606                     '<img id="{id}-arrowEl" src="{blank}" class="' + Ext.baseCSSPrefix + 'menu-item-arrow" />',
86607                 '</tpl>',
86608             '</a>',
86609         '</tpl>'
86610     ],
86611
86612     maskOnDisable: false,
86613
86614     
86615
86616     activate: function() {
86617         var me = this;
86618
86619         if (!me.activated && me.canActivate && me.rendered && !me.isDisabled() && me.isVisible()) {
86620             me.el.addCls(me.activeCls);
86621             me.focus();
86622             me.activated = true;
86623             me.fireEvent('activate', me);
86624         }
86625     },
86626
86627     blur: function() {
86628         this.$focused = false;
86629         this.callParent(arguments);
86630     },
86631
86632     deactivate: function() {
86633         var me = this;
86634
86635         if (me.activated) {
86636             me.el.removeCls(me.activeCls);
86637             me.blur();
86638             me.hideMenu();
86639             me.activated = false;
86640             me.fireEvent('deactivate', me);
86641         }
86642     },
86643
86644     deferExpandMenu: function() {
86645         var me = this;
86646
86647         if (!me.menu.rendered || !me.menu.isVisible()) {
86648             me.parentMenu.activeChild = me.menu;
86649             me.menu.parentItem = me;
86650             me.menu.parentMenu = me.menu.ownerCt = me.parentMenu;
86651             me.menu.showBy(me, me.menuAlign);
86652         }
86653     },
86654
86655     deferHideMenu: function() {
86656         if (this.menu.isVisible()) {
86657             this.menu.hide();
86658         }
86659     },
86660
86661     deferHideParentMenus: function() {
86662         Ext.menu.Manager.hideAll();
86663     },
86664
86665     expandMenu: function(delay) {
86666         var me = this;
86667
86668         if (me.menu) {
86669             clearTimeout(me.hideMenuTimer);
86670             if (delay === 0) {
86671                 me.deferExpandMenu();
86672             } else {
86673                 me.expandMenuTimer = Ext.defer(me.deferExpandMenu, Ext.isNumber(delay) ? delay : me.menuExpandDelay, me);
86674             }
86675         }
86676     },
86677
86678     focus: function() {
86679         this.$focused = true;
86680         this.callParent(arguments);
86681     },
86682
86683     getRefItems: function(deep){
86684         var menu = this.menu,
86685             items;
86686
86687         if (menu) {
86688             items = menu.getRefItems(deep);
86689             items.unshift(menu);
86690         }
86691         return items || [];
86692     },
86693
86694     hideMenu: function(delay) {
86695         var me = this;
86696
86697         if (me.menu) {
86698             clearTimeout(me.expandMenuTimer);
86699             me.hideMenuTimer = Ext.defer(me.deferHideMenu, Ext.isNumber(delay) ? delay : me.menuHideDelay, me);
86700         }
86701     },
86702
86703     initComponent: function() {
86704         var me = this,
86705             prefix = Ext.baseCSSPrefix,
86706             cls = [prefix + 'menu-item'];
86707
86708         me.addEvents(
86709             
86710             'activate',
86711
86712             
86713             'click',
86714
86715             
86716             'deactivate'
86717         );
86718
86719         if (me.plain) {
86720             cls.push(prefix + 'menu-item-plain');
86721         }
86722
86723         if (me.cls) {
86724             cls.push(me.cls);
86725         }
86726
86727         me.cls = cls.join(' ');
86728
86729         if (me.menu) {
86730             me.menu = Ext.menu.Manager.get(me.menu);
86731         }
86732
86733         me.callParent(arguments);
86734     },
86735
86736     onClick: function(e) {
86737         var me = this;
86738
86739         if (!me.href) {
86740             e.stopEvent();
86741         }
86742
86743         if (me.disabled) {
86744             return;
86745         }
86746
86747         if (me.hideOnClick) {
86748             me.deferHideParentMenusTimer = Ext.defer(me.deferHideParentMenus, me.clickHideDelay, me);
86749         }
86750
86751         Ext.callback(me.handler, me.scope || me, [me, e]);
86752         me.fireEvent('click', me, e);
86753
86754         if (!me.hideOnClick) {
86755             me.focus();
86756         }
86757     },
86758
86759     onDestroy: function() {
86760         var me = this;
86761
86762         clearTimeout(me.expandMenuTimer);
86763         clearTimeout(me.hideMenuTimer);
86764         clearTimeout(me.deferHideParentMenusTimer);
86765
86766         if (me.menu) {
86767             delete me.menu.parentItem;
86768             delete me.menu.parentMenu;
86769             delete me.menu.ownerCt;
86770             if (me.destroyMenu !== false) {
86771                 me.menu.destroy();
86772             }
86773         }
86774         me.callParent(arguments);
86775     },
86776
86777     onRender: function(ct, pos) {
86778         var me = this,
86779             blank = Ext.BLANK_IMAGE_URL;
86780
86781         Ext.applyIf(me.renderData, {
86782             href: me.href || '#',
86783             hrefTarget: me.hrefTarget,
86784             icon: me.icon || blank,
86785             iconCls: me.iconCls + (me.checkChangeDisabled ? ' ' + me.disabledCls : ''),
86786             menu: Ext.isDefined(me.menu),
86787             plain: me.plain,
86788             text: me.text,
86789             blank: blank
86790         });
86791
86792         me.addChildEls('itemEl', 'iconEl', 'textEl', 'arrowEl');
86793
86794         me.callParent(arguments);
86795     },
86796
86797     
86798     setHandler: function(fn, scope) {
86799         this.handler = fn || null;
86800         this.scope = scope;
86801     },
86802
86803     
86804     setIconCls: function(iconCls) {
86805         var me = this;
86806
86807         if (me.iconEl) {
86808             if (me.iconCls) {
86809                 me.iconEl.removeCls(me.iconCls);
86810             }
86811
86812             if (iconCls) {
86813                 me.iconEl.addCls(iconCls);
86814             }
86815         }
86816
86817         me.iconCls = iconCls;
86818     },
86819
86820     
86821     setText: function(text) {
86822         var me = this,
86823             el = me.textEl || me.el;
86824
86825         me.text = text;
86826
86827         if (me.rendered) {
86828             el.update(text || '');
86829             
86830             me.ownerCt.redoComponentLayout();
86831         }
86832     }
86833 });
86834
86835
86836 Ext.define('Ext.menu.CheckItem', {
86837     extend: 'Ext.menu.Item',
86838     alias: 'widget.menucheckitem',
86839
86840     
86841     checkedCls: Ext.baseCSSPrefix + 'menu-item-checked',
86842     
86843     uncheckedCls: Ext.baseCSSPrefix + 'menu-item-unchecked',
86844     
86845     groupCls: Ext.baseCSSPrefix + 'menu-group-icon',
86846
86847     
86848     hideOnClick: false,
86849
86850     afterRender: function() {
86851         var me = this;
86852         this.callParent();
86853         me.checked = !me.checked;
86854         me.setChecked(!me.checked, true);
86855     },
86856
86857     initComponent: function() {
86858         var me = this;
86859         me.addEvents(
86860             
86861             'beforecheckchange',
86862
86863             
86864             'checkchange'
86865         );
86866
86867         me.callParent(arguments);
86868
86869         Ext.menu.Manager.registerCheckable(me);
86870
86871         if (me.group) {
86872             if (!me.iconCls) {
86873                 me.iconCls = me.groupCls;
86874             }
86875             if (me.initialConfig.hideOnClick !== false) {
86876                 me.hideOnClick = true;
86877             }
86878         }
86879     },
86880
86881     
86882     disableCheckChange: function() {
86883         var me = this;
86884
86885         if (me.iconEl) {
86886             me.iconEl.addCls(me.disabledCls);
86887         }
86888         me.checkChangeDisabled = true;
86889     },
86890
86891     
86892     enableCheckChange: function() {
86893         var me = this;
86894
86895         me.iconEl.removeCls(me.disabledCls);
86896         me.checkChangeDisabled = false;
86897     },
86898
86899     onClick: function(e) {
86900         var me = this;
86901         if(!me.disabled && !me.checkChangeDisabled && !(me.checked && me.group)) {
86902             me.setChecked(!me.checked);
86903         }
86904         this.callParent([e]);
86905     },
86906
86907     onDestroy: function() {
86908         Ext.menu.Manager.unregisterCheckable(this);
86909         this.callParent(arguments);
86910     },
86911
86912     
86913     setChecked: function(checked, suppressEvents) {
86914         var me = this;
86915         if (me.checked !== checked && (suppressEvents || me.fireEvent('beforecheckchange', me, checked) !== false)) {
86916             if (me.el) {
86917                 me.el[checked  ? 'addCls' : 'removeCls'](me.checkedCls)[!checked ? 'addCls' : 'removeCls'](me.uncheckedCls);
86918             }
86919             me.checked = checked;
86920             Ext.menu.Manager.onCheckChange(me, checked);
86921             if (!suppressEvents) {
86922                 Ext.callback(me.checkHandler, me.scope, [me, checked]);
86923                 me.fireEvent('checkchange', me, checked);
86924             }
86925         }
86926     }
86927 });
86928
86929
86930 Ext.define('Ext.menu.KeyNav', {
86931     extend: 'Ext.util.KeyNav',
86932
86933     requires: ['Ext.FocusManager'],
86934     
86935     constructor: function(menu) {
86936         var me = this;
86937
86938         me.menu = menu;
86939         me.callParent([menu.el, {
86940             down: me.down,
86941             enter: me.enter,
86942             esc: me.escape,
86943             left: me.left,
86944             right: me.right,
86945             space: me.enter,
86946             tab: me.tab,
86947             up: me.up
86948         }]);
86949     },
86950
86951     down: function(e) {
86952         var me = this,
86953             fi = me.menu.focusedItem;
86954
86955         if (fi && e.getKey() == Ext.EventObject.DOWN && me.isWhitelisted(fi)) {
86956             return true;
86957         }
86958         me.focusNextItem(1);
86959     },
86960
86961     enter: function(e) {
86962         var menu = this.menu,
86963             focused = menu.focusedItem;
86964  
86965         if (menu.activeItem) {
86966             menu.onClick(e);
86967         } else if (focused && focused.isFormField) {
86968             
86969             return true;
86970         }
86971     },
86972
86973     escape: function(e) {
86974         Ext.menu.Manager.hideAll();
86975     },
86976
86977     focusNextItem: function(step) {
86978         var menu = this.menu,
86979             items = menu.items,
86980             focusedItem = menu.focusedItem,
86981             startIdx = focusedItem ? items.indexOf(focusedItem) : -1,
86982             idx = startIdx + step;
86983
86984         while (idx != startIdx) {
86985             if (idx < 0) {
86986                 idx = items.length - 1;
86987             } else if (idx >= items.length) {
86988                 idx = 0;
86989             }
86990
86991             var item = items.getAt(idx);
86992             if (menu.canActivateItem(item)) {
86993                 menu.setActiveItem(item);
86994                 break;
86995             }
86996             idx += step;
86997         }
86998     },
86999
87000     isWhitelisted: function(item) {
87001         return Ext.FocusManager.isWhitelisted(item);
87002     },
87003
87004     left: function(e) {
87005         var menu = this.menu,
87006             fi = menu.focusedItem,
87007             ai = menu.activeItem;
87008
87009         if (fi && this.isWhitelisted(fi)) {
87010             return true;
87011         }
87012
87013         menu.hide();
87014         if (menu.parentMenu) {
87015             menu.parentMenu.focus();
87016         }
87017     },
87018
87019     right: function(e) {
87020         var menu = this.menu,
87021             fi = menu.focusedItem,
87022             ai = menu.activeItem,
87023             am;
87024
87025         if (fi && this.isWhitelisted(fi)) {
87026             return true;
87027         }
87028
87029         if (ai) {
87030             am = menu.activeItem.menu;
87031             if (am) {
87032                 ai.expandMenu(0);
87033                 Ext.defer(function() {
87034                     am.setActiveItem(am.items.getAt(0));
87035                 }, 25);
87036             }
87037         }
87038     },
87039
87040     tab: function(e) {
87041         var me = this;
87042
87043         if (e.shiftKey) {
87044             me.up(e);
87045         } else {
87046             me.down(e);
87047         }
87048     },
87049
87050     up: function(e) {
87051         var me = this,
87052             fi = me.menu.focusedItem;
87053
87054         if (fi && e.getKey() == Ext.EventObject.UP && me.isWhitelisted(fi)) {
87055             return true;
87056         }
87057         me.focusNextItem(-1);
87058     }
87059 });
87060
87061 Ext.define('Ext.menu.Separator', {
87062     extend: 'Ext.menu.Item',
87063     alias: 'widget.menuseparator',
87064
87065     
87066
87067     
87068     canActivate: false,
87069
87070     
87071
87072     
87073
87074     
87075
87076     focusable: false,
87077
87078     
87079
87080     
87081
87082     
87083     hideOnClick: false,
87084
87085     
87086
87087     
87088
87089     
87090
87091     
87092
87093     
87094
87095     
87096
87097     
87098     plain: true,
87099
87100     
87101     separatorCls: Ext.baseCSSPrefix + 'menu-item-separator',
87102
87103     
87104     text: '&#160;',
87105
87106     onRender: function(ct, pos) {
87107         var me = this,
87108             sepCls = me.separatorCls;
87109
87110         me.cls += ' ' + sepCls;
87111
87112         me.callParent(arguments);
87113     }
87114 });
87115
87116 Ext.define('Ext.menu.Menu', {
87117     extend: 'Ext.panel.Panel',
87118     alias: 'widget.menu',
87119     requires: [
87120         'Ext.layout.container.Fit',
87121         'Ext.layout.container.VBox',
87122         'Ext.menu.CheckItem',
87123         'Ext.menu.Item',
87124         'Ext.menu.KeyNav',
87125         'Ext.menu.Manager',
87126         'Ext.menu.Separator'
87127     ],
87128
87129     
87130
87131     
87132     allowOtherMenus: false,
87133
87134     
87135     ariaRole: 'menu',
87136
87137     
87138
87139     
87140     defaultAlign: 'tl-bl?',
87141
87142     
87143     floating: true,
87144
87145     
87146     constrain: true,
87147
87148     
87149     hidden: true,
87150
87151     hideMode: 'visibility',
87152
87153     
87154     ignoreParentClicks: false,
87155
87156     isMenu: true,
87157
87158     
87159
87160     
87161     showSeparator : true,
87162
87163     
87164     minWidth: 120,
87165
87166     
87167
87168     initComponent: function() {
87169         var me = this,
87170             prefix = Ext.baseCSSPrefix,
87171             cls = [prefix + 'menu'],
87172             bodyCls = me.bodyCls ? [me.bodyCls] : [];
87173
87174         me.addEvents(
87175             
87176             'click',
87177
87178             
87179             'mouseenter',
87180
87181             
87182             'mouseleave',
87183
87184             
87185             'mouseover'
87186         );
87187
87188         Ext.menu.Manager.register(me);
87189
87190         
87191         if (me.plain) {
87192             cls.push(prefix + 'menu-plain');
87193         }
87194         me.cls = cls.join(' ');
87195
87196         
87197         bodyCls.unshift(prefix + 'menu-body');
87198         me.bodyCls = bodyCls.join(' ');
87199
87200         
87201         
87202         
87203         
87204         me.layout = {
87205             type: 'vbox',
87206             align: 'stretchmax',
87207             autoSize: true,
87208             clearInnerCtOnLayout: true,
87209             overflowHandler: 'Scroller'
87210         };
87211
87212         
87213         if (me.floating === false && me.initialConfig.hidden !== true) {
87214             me.hidden = false;
87215         }
87216
87217         me.callParent(arguments);
87218
87219         me.on('beforeshow', function() {
87220             var hasItems = !!me.items.length;
87221             
87222             
87223             
87224             if (hasItems && me.rendered) {
87225                 me.el.setStyle('visibility', null);
87226             }
87227             return hasItems;
87228         });
87229     },
87230
87231     afterRender: function(ct) {
87232         var me = this,
87233             prefix = Ext.baseCSSPrefix,
87234             space = '&#160;';
87235
87236         me.callParent(arguments);
87237
87238         
87239         if (me.showSeparator) {
87240             me.iconSepEl = me.layout.getRenderTarget().insertFirst({
87241                 cls: prefix + 'menu-icon-separator',
87242                 html: space
87243             });
87244         }
87245
87246         me.focusEl = me.el.createChild({
87247             cls: prefix + 'menu-focus',
87248             tabIndex: '-1',
87249             html: space
87250         });
87251
87252         me.mon(me.el, {
87253             click: me.onClick,
87254             mouseover: me.onMouseOver,
87255             scope: me
87256         });
87257         me.mouseMonitor = me.el.monitorMouseLeave(100, me.onMouseLeave, me);
87258
87259         if (me.showSeparator && ((!Ext.isStrict && Ext.isIE) || Ext.isIE6)) {
87260             me.iconSepEl.setHeight(me.el.getHeight());
87261         }
87262
87263         me.keyNav = Ext.create('Ext.menu.KeyNav', me);
87264     },
87265
87266     afterLayout: function() {
87267         var me = this;
87268         me.callParent(arguments);
87269
87270         
87271         
87272         
87273         
87274         if ((!Ext.isStrict && Ext.isIE) || Ext.isIE6) {
87275             var innerCt = me.layout.getRenderTarget(),
87276                 innerCtWidth = 0,
87277                 dis = me.dockedItems,
87278                 l = dis.length,
87279                 i = 0,
87280                 di, clone, newWidth;
87281
87282             innerCtWidth = innerCt.getWidth();
87283
87284             newWidth = innerCtWidth + me.body.getBorderWidth('lr') + me.body.getPadding('lr');
87285
87286             
87287             me.body.setWidth(newWidth);
87288
87289             
87290             for (; i < l, di = dis.getAt(i); i++) {
87291                 if (di.dock == 'left' || di.dock == 'right') {
87292                     newWidth += di.getWidth();
87293                 }
87294             }
87295             me.el.setWidth(newWidth);
87296         }
87297     },
87298     
87299     getBubbleTarget: function(){
87300         return this.parentMenu || this.callParent();
87301     },
87302
87303     
87304     canActivateItem: function(item) {
87305         return item && !item.isDisabled() && item.isVisible() && (item.canActivate || item.getXTypes().indexOf('menuitem') < 0);
87306     },
87307
87308     
87309     deactivateActiveItem: function() {
87310         var me = this;
87311
87312         if (me.activeItem) {
87313             me.activeItem.deactivate();
87314             if (!me.activeItem.activated) {
87315                 delete me.activeItem;
87316             }
87317         }
87318
87319         
87320         if (me.focusedItem && !me.filtered) {
87321             me.focusedItem.blur();
87322             if (!me.focusedItem.$focused) {
87323                 delete me.focusedItem;
87324             }
87325         }
87326     },
87327
87328     clearStretch: function () {
87329         
87330         
87331         if (this.rendered) {
87332             this.items.each(function (item) {
87333                 
87334                 if (item.componentLayout) {
87335                     delete item.componentLayout.lastComponentSize;
87336                 }
87337                 if (item.el) {
87338                     item.el.setWidth(null);
87339                 }
87340             });
87341         }
87342     },
87343
87344     onAdd: function () {
87345         var me = this;
87346
87347         me.clearStretch();
87348         me.callParent(arguments);
87349
87350         if (Ext.isIE6 || Ext.isIE7) {
87351             
87352             Ext.Function.defer(me.doComponentLayout, 10, me);
87353         }
87354     },
87355
87356     onRemove: function () {
87357         this.clearStretch();
87358         this.callParent(arguments);
87359
87360     },
87361
87362     redoComponentLayout: function () {
87363         if (this.rendered) {
87364             this.clearStretch();
87365             this.doComponentLayout();
87366         }
87367     },
87368
87369     
87370     getFocusEl: function() {
87371         return this.focusEl;
87372     },
87373
87374     
87375     hide: function() {
87376         this.deactivateActiveItem();
87377         this.callParent(arguments);
87378     },
87379
87380     
87381     getItemFromEvent: function(e) {
87382         return this.getChildByElement(e.getTarget());
87383     },
87384
87385     lookupComponent: function(cmp) {
87386         var me = this;
87387
87388         if (Ext.isString(cmp)) {
87389             cmp = me.lookupItemFromString(cmp);
87390         } else if (Ext.isObject(cmp)) {
87391             cmp = me.lookupItemFromObject(cmp);
87392         }
87393
87394         
87395         
87396         cmp.minWidth = cmp.minWidth || me.minWidth;
87397
87398         return cmp;
87399     },
87400
87401     
87402     lookupItemFromObject: function(cmp) {
87403         var me = this,
87404             prefix = Ext.baseCSSPrefix,
87405             cls,
87406             intercept;
87407
87408         if (!cmp.isComponent) {
87409             if (!cmp.xtype) {
87410                 cmp = Ext.create('Ext.menu.' + (Ext.isBoolean(cmp.checked) ? 'Check': '') + 'Item', cmp);
87411             } else {
87412                 cmp = Ext.ComponentManager.create(cmp, cmp.xtype);
87413             }
87414         }
87415
87416         if (cmp.isMenuItem) {
87417             cmp.parentMenu = me;
87418         }
87419
87420         if (!cmp.isMenuItem && !cmp.dock) {
87421             cls = [prefix + 'menu-item', prefix + 'menu-item-cmp'];
87422             intercept = Ext.Function.createInterceptor;
87423
87424             
87425             cmp.focus = intercept(cmp.focus, function() {
87426                 this.$focused = true;
87427             }, cmp);
87428             cmp.blur = intercept(cmp.blur, function() {
87429                 this.$focused = false;
87430             }, cmp);
87431
87432             if (!me.plain && (cmp.indent === true || cmp.iconCls === 'no-icon')) {
87433                 cls.push(prefix + 'menu-item-indent');
87434             }
87435
87436             if (cmp.rendered) {
87437                 cmp.el.addCls(cls);
87438             } else {
87439                 cmp.cls = (cmp.cls ? cmp.cls : '') + ' ' + cls.join(' ');
87440             }
87441             cmp.isMenuItem = true;
87442         }
87443         return cmp;
87444     },
87445
87446     
87447     lookupItemFromString: function(cmp) {
87448         return (cmp == 'separator' || cmp == '-') ?
87449             Ext.createWidget('menuseparator')
87450             : Ext.createWidget('menuitem', {
87451                 canActivate: false,
87452                 hideOnClick: false,
87453                 plain: true,
87454                 text: cmp
87455             });
87456     },
87457
87458     onClick: function(e) {
87459         var me = this,
87460             item;
87461
87462         if (me.disabled) {
87463             e.stopEvent();
87464             return;
87465         }
87466
87467         if ((e.getTarget() == me.focusEl.dom) || e.within(me.layout.getRenderTarget())) {
87468             item = me.getItemFromEvent(e) || me.activeItem;
87469
87470             if (item) {
87471                 if (item.getXTypes().indexOf('menuitem') >= 0) {
87472                     if (!item.menu || !me.ignoreParentClicks) {
87473                         item.onClick(e);
87474                     } else {
87475                         e.stopEvent();
87476                     }
87477                 }
87478             }
87479             me.fireEvent('click', me, item, e);
87480         }
87481     },
87482
87483     onDestroy: function() {
87484         var me = this;
87485
87486         Ext.menu.Manager.unregister(me);
87487         if (me.rendered) {
87488             me.el.un(me.mouseMonitor);
87489             me.keyNav.destroy();
87490             delete me.keyNav;
87491         }
87492         me.callParent(arguments);
87493     },
87494
87495     onMouseLeave: function(e) {
87496         var me = this;
87497
87498         me.deactivateActiveItem();
87499
87500         if (me.disabled) {
87501             return;
87502         }
87503
87504         me.fireEvent('mouseleave', me, e);
87505     },
87506
87507     onMouseOver: function(e) {
87508         var me = this,
87509             fromEl = e.getRelatedTarget(),
87510             mouseEnter = !me.el.contains(fromEl),
87511             item = me.getItemFromEvent(e);
87512
87513         if (mouseEnter && me.parentMenu) {
87514             me.parentMenu.setActiveItem(me.parentItem);
87515             me.parentMenu.mouseMonitor.mouseenter();
87516         }
87517
87518         if (me.disabled) {
87519             return;
87520         }
87521
87522         if (item) {
87523             me.setActiveItem(item);
87524             if (item.activated && item.expandMenu) {
87525                 item.expandMenu();
87526             }
87527         }
87528         if (mouseEnter) {
87529             me.fireEvent('mouseenter', me, e);
87530         }
87531         me.fireEvent('mouseover', me, item, e);
87532     },
87533
87534     setActiveItem: function(item) {
87535         var me = this;
87536
87537         if (item && (item != me.activeItem && item != me.focusedItem)) {
87538             me.deactivateActiveItem();
87539             if (me.canActivateItem(item)) {
87540                 if (item.activate) {
87541                     item.activate();
87542                     if (item.activated) {
87543                         me.activeItem = item;
87544                         me.focusedItem = item;
87545                         me.focus();
87546                     }
87547                 } else {
87548                     item.focus();
87549                     me.focusedItem = item;
87550                 }
87551             }
87552             item.el.scrollIntoView(me.layout.getRenderTarget());
87553         }
87554     },
87555
87556     
87557     showBy: function(cmp, pos, off) {
87558         var me = this,
87559             xy,
87560             region;
87561
87562         if (me.floating && cmp) {
87563             me.layout.autoSize = true;
87564
87565             
87566             me.doAutoRender();
87567             delete me.needsLayout;
87568
87569             
87570             cmp = cmp.el || cmp;
87571
87572             
87573             xy = me.el.getAlignToXY(cmp, pos || me.defaultAlign, off);
87574             if (me.floatParent) {
87575                 region = me.floatParent.getTargetEl().getViewRegion();
87576                 xy[0] -= region.x;
87577                 xy[1] -= region.y;
87578             }
87579             me.showAt(xy);
87580         }
87581         return me;
87582     },
87583
87584     doConstrain : function() {
87585         var me = this,
87586             y = me.el.getY(),
87587             max, full,
87588             vector,
87589             returnY = y, normalY, parentEl, scrollTop, viewHeight;
87590
87591         delete me.height;
87592         me.setSize();
87593         full = me.getHeight();
87594         if (me.floating) {
87595             
87596             parentEl = Ext.fly(me.el.getScopeParent());
87597             scrollTop = parentEl.getScroll().top;
87598             viewHeight = parentEl.getViewSize().height;
87599             
87600             
87601             normalY = y - scrollTop;
87602             max = me.maxHeight ? me.maxHeight : viewHeight - normalY;
87603             if (full > viewHeight) {
87604                 max = viewHeight;
87605                 
87606                 returnY = y - normalY;
87607             } else if (max < full) {
87608                 returnY = y - (full - max);
87609                 max = full;
87610             }
87611         }else{
87612             max = me.getHeight();
87613         }
87614         
87615         if (me.maxHeight){
87616             max = Math.min(me.maxHeight, max);
87617         }
87618         if (full > max && max > 0){
87619             me.layout.autoSize = false;
87620             me.setHeight(max);
87621             if (me.showSeparator){
87622                 me.iconSepEl.setHeight(me.layout.getRenderTarget().dom.scrollHeight);
87623             }
87624         }
87625         vector = me.getConstrainVector(me.el.getScopeParent());
87626         if (vector) {
87627             me.setPosition(me.getPosition()[0] + vector[0]);
87628         }
87629         me.el.setY(returnY);
87630     }
87631 });
87632
87633
87634  Ext.define('Ext.menu.ColorPicker', {
87635      extend: 'Ext.menu.Menu',
87636
87637      alias: 'widget.colormenu',
87638
87639      requires: [
87640         'Ext.picker.Color'
87641      ],
87642
87643     
87644     hideOnClick : true,
87645
87646     
87647     pickerId : null,
87648
87649     
87650
87651     
87652
87653     
87654
87655     
87656
87657     initComponent : function(){
87658         var me = this,
87659             cfg = Ext.apply({}, me.initialConfig);
87660
87661         
87662         delete cfg.listeners;
87663         Ext.apply(me, {
87664             plain: true,
87665             showSeparator: false,
87666             items: Ext.applyIf({
87667                 cls: Ext.baseCSSPrefix + 'menu-color-item',
87668                 id: me.pickerId,
87669                 xtype: 'colorpicker'
87670             }, cfg)
87671         });
87672
87673         me.callParent(arguments);
87674
87675         me.picker = me.down('colorpicker');
87676
87677         
87678         me.relayEvents(me.picker, ['select']);
87679
87680         if (me.hideOnClick) {
87681             me.on('select', me.hidePickerOnSelect, me);
87682         }
87683     },
87684
87685     
87686     hidePickerOnSelect: function() {
87687         Ext.menu.Manager.hideAll();
87688     }
87689  });
87690
87691  Ext.define('Ext.menu.DatePicker', {
87692      extend: 'Ext.menu.Menu',
87693
87694      alias: 'widget.datemenu',
87695
87696      requires: [
87697         'Ext.picker.Date'
87698      ],
87699
87700     
87701     hideOnClick : true,
87702
87703     
87704     pickerId : null,
87705
87706     
87707
87708     
87709
87710     
87711
87712     
87713
87714     initComponent : function(){
87715         var me = this;
87716
87717         Ext.apply(me, {
87718             showSeparator: false,
87719             plain: true,
87720             border: false,
87721             bodyPadding: 0, 
87722             items: Ext.applyIf({
87723                 cls: Ext.baseCSSPrefix + 'menu-date-item',
87724                 id: me.pickerId,
87725                 xtype: 'datepicker'
87726             }, me.initialConfig)
87727         });
87728
87729         me.callParent(arguments);
87730
87731         me.picker = me.down('datepicker');
87732         
87733         me.relayEvents(me.picker, ['select']);
87734
87735         if (me.hideOnClick) {
87736             me.on('select', me.hidePickerOnSelect, me);
87737         }
87738     },
87739
87740     hidePickerOnSelect: function() {
87741         Ext.menu.Manager.hideAll();
87742     }
87743  });
87744
87745 Ext.define('Ext.panel.Tool', {
87746     extend: 'Ext.Component',
87747     requires: ['Ext.tip.QuickTipManager'],
87748     alias: 'widget.tool',
87749
87750     baseCls: Ext.baseCSSPrefix + 'tool',
87751     disabledCls: Ext.baseCSSPrefix + 'tool-disabled',
87752     toolPressedCls: Ext.baseCSSPrefix + 'tool-pressed',
87753     toolOverCls: Ext.baseCSSPrefix + 'tool-over',
87754     ariaRole: 'button',
87755     renderTpl: ['<img id="{id}-toolEl" src="{blank}" class="{baseCls}-{type}" role="presentation"/>'],
87756
87757     
87758
87759     
87760
87761     
87762
87763     
87764
87765      
87766     tooltipType: 'qtip',
87767
87768     
87769     stopEvent: true,
87770
87771     initComponent: function() {
87772         var me = this;
87773         me.addEvents(
87774             
87775             'click'
87776         );
87777
87778
87779         me.type = me.type || me.id;
87780
87781         Ext.applyIf(me.renderData, {
87782             baseCls: me.baseCls,
87783             blank: Ext.BLANK_IMAGE_URL,
87784             type: me.type
87785         });
87786
87787         me.addChildEls('toolEl');
87788
87789         
87790         me.tooltip = me.tooltip || me.qtip;
87791         me.callParent();
87792     },
87793
87794     
87795     afterRender: function() {
87796         var me = this,
87797             attr;
87798
87799         me.callParent(arguments);
87800         if (me.tooltip) {
87801             if (Ext.isObject(me.tooltip)) {
87802                 Ext.tip.QuickTipManager.register(Ext.apply({
87803                     target: me.id
87804                 }, me.tooltip));
87805             }
87806             else {
87807                 attr = me.tooltipType == 'qtip' ? 'data-qtip' : 'title';
87808                 me.toolEl.dom.setAttribute(attr, me.tooltip);
87809             }
87810         }
87811
87812         me.mon(me.toolEl, {
87813             click: me.onClick,
87814             mousedown: me.onMouseDown,
87815             mouseover: me.onMouseOver,
87816             mouseout: me.onMouseOut,
87817             scope: me
87818         });
87819     },
87820
87821     
87822     setType: function(type) {
87823         var me = this;
87824
87825         me.type = type;
87826         if (me.rendered) {
87827             me.toolEl.dom.className = me.baseCls + '-' + type;
87828         }
87829         return me;
87830     },
87831
87832     
87833     bindTo: function(component) {
87834         this.owner = component;
87835     },
87836
87837     
87838     onClick: function(e, target) {
87839         var me = this,
87840             owner;
87841
87842         if (me.disabled) {
87843             return false;
87844         }
87845         owner = me.owner || me.ownerCt;
87846
87847         
87848         me.el.removeCls(me.toolPressedCls);
87849         me.el.removeCls(me.toolOverCls);
87850
87851         if (me.stopEvent !== false) {
87852             e.stopEvent();
87853         }
87854
87855         Ext.callback(me.handler, me.scope || me, [e, target, owner, me]);
87856         me.fireEvent('click', me, e);
87857         return true;
87858     },
87859
87860     
87861     onDestroy: function(){
87862         if (Ext.isObject(this.tooltip)) {
87863             Ext.tip.QuickTipManager.unregister(this.id);
87864         }
87865         this.callParent();
87866     },
87867
87868     
87869     onMouseDown: function() {
87870         if (this.disabled) {
87871             return false;
87872         }
87873
87874         this.el.addCls(this.toolPressedCls);
87875     },
87876
87877     
87878     onMouseOver: function() {
87879         if (this.disabled) {
87880             return false;
87881         }
87882         this.el.addCls(this.toolOverCls);
87883     },
87884
87885     
87886     onMouseOut: function() {
87887         this.el.removeCls(this.toolOverCls);
87888     }
87889 });
87890
87891 Ext.define('Ext.resizer.Handle', {
87892     extend: 'Ext.Component',
87893     handleCls: '',
87894     baseHandleCls: Ext.baseCSSPrefix + 'resizable-handle',
87895     
87896     
87897     region: '',
87898
87899     onRender: function() {
87900         this.addCls(
87901             this.baseHandleCls,
87902             this.baseHandleCls + '-' + this.region,
87903             this.handleCls
87904         );
87905         this.callParent(arguments);
87906         this.el.unselectable();
87907     }
87908 });
87909
87910
87911 Ext.define('Ext.resizer.Resizer', {
87912     mixins: {
87913         observable: 'Ext.util.Observable'
87914     },
87915     uses: ['Ext.resizer.ResizeTracker', 'Ext.Component'],
87916
87917     alternateClassName: 'Ext.Resizable',
87918
87919     handleCls: Ext.baseCSSPrefix + 'resizable-handle',
87920     pinnedCls: Ext.baseCSSPrefix + 'resizable-pinned',
87921     overCls:   Ext.baseCSSPrefix + 'resizable-over',
87922     wrapCls:   Ext.baseCSSPrefix + 'resizable-wrap',
87923
87924     
87925     dynamic: true,
87926
87927     
87928     handles: 's e se',
87929
87930     
87931     height : null,
87932
87933     
87934     width : null,
87935
87936     
87937     heightIncrement : 0,
87938
87939     
87940     widthIncrement : 0,
87941
87942     
87943     minHeight : 20,
87944
87945     
87946     minWidth : 20,
87947
87948     
87949     maxHeight : 10000,
87950
87951     
87952     maxWidth : 10000,
87953
87954     
87955     pinned: false,
87956
87957     
87958     preserveRatio: false,
87959
87960     
87961     transparent: false,
87962
87963     
87964
87965     possiblePositions: {
87966         n:  'north',
87967         s:  'south',
87968         e:  'east',
87969         w:  'west',
87970         se: 'southeast',
87971         sw: 'southwest',
87972         nw: 'northwest',
87973         ne: 'northeast'
87974     },
87975
87976     
87977
87978     
87979
87980     constructor: function(config) {
87981         var me = this,
87982             target,
87983             tag,
87984             handles = me.handles,
87985             handleCls,
87986             possibles,
87987             len,
87988             i = 0,
87989             pos;
87990
87991         this.addEvents(
87992             
87993             'beforeresize',
87994             
87995             'resizedrag',
87996             
87997             'resize'
87998         );
87999
88000         if (Ext.isString(config) || Ext.isElement(config) || config.dom) {
88001             target = config;
88002             config = arguments[1] || {};
88003             config.target = target;
88004         }
88005         
88006         me.mixins.observable.constructor.call(me, config);
88007
88008         
88009         
88010         target = me.target;
88011         if (target) {
88012             if (target.isComponent) {
88013                 me.el = target.getEl();
88014                 if (target.minWidth) {
88015                     me.minWidth = target.minWidth;
88016                 }
88017                 if (target.minHeight) {
88018                     me.minHeight = target.minHeight;
88019                 }
88020                 if (target.maxWidth) {
88021                     me.maxWidth = target.maxWidth;
88022                 }
88023                 if (target.maxHeight) {
88024                     me.maxHeight = target.maxHeight;
88025                 }
88026                 if (target.floating) {
88027                     if (!this.hasOwnProperty('handles')) {
88028                         this.handles = 'n ne e se s sw w nw';
88029                     }
88030                 }
88031             } else {
88032                 me.el = me.target = Ext.get(target);
88033             }
88034         }
88035         
88036         else {
88037             me.target = me.el = Ext.get(me.el);
88038         }
88039
88040         
88041         
88042         
88043         tag = me.el.dom.tagName;
88044         if (tag == 'TEXTAREA' || tag == 'IMG') {
88045             
88046             me.originalTarget = me.target;
88047             me.target = me.el = me.el.wrap({
88048                 cls: me.wrapCls,
88049                 id: me.el.id + '-rzwrap'
88050             });
88051
88052             
88053             me.el.setPositioning(me.originalTarget.getPositioning());
88054             me.originalTarget.clearPositioning();
88055             var box = me.originalTarget.getBox();
88056             me.el.setBox(box);
88057         }
88058
88059         
88060         
88061         me.el.position();
88062         if (me.pinned) {
88063             me.el.addCls(me.pinnedCls);
88064         }
88065
88066         
88067         me.resizeTracker = Ext.create('Ext.resizer.ResizeTracker', {
88068             disabled: me.disabled,
88069             target: me.target,
88070             constrainTo: me.constrainTo,
88071             overCls: me.overCls,
88072             throttle: me.throttle,
88073             originalTarget: me.originalTarget,
88074             delegate: '.' + me.handleCls,
88075             dynamic: me.dynamic,
88076             preserveRatio: me.preserveRatio,
88077             heightIncrement: me.heightIncrement,
88078             widthIncrement: me.widthIncrement,
88079             minHeight: me.minHeight,
88080             maxHeight: me.maxHeight,
88081             minWidth: me.minWidth,
88082             maxWidth: me.maxWidth
88083         });
88084
88085         
88086         me.resizeTracker.on('mousedown', me.onBeforeResize, me);
88087         me.resizeTracker.on('drag', me.onResize, me);
88088         me.resizeTracker.on('dragend', me.onResizeEnd, me);
88089
88090         if (me.handles == 'all') {
88091             me.handles = 'n s e w ne nw se sw';
88092         }
88093
88094         handles = me.handles = me.handles.split(/ |\s*?[,;]\s*?/);
88095         possibles = me.possiblePositions;
88096         len = handles.length;
88097         handleCls = me.handleCls + ' ' + (this.target.isComponent ? (me.target.baseCls + '-handle ') : '') + me.handleCls + '-';
88098
88099         for(; i < len; i++){
88100             
88101             if (handles[i] && possibles[handles[i]]) {
88102                 pos = possibles[handles[i]];
88103                 
88104
88105                 me[pos] = Ext.create('Ext.Component', {
88106                     owner: this,
88107                     region: pos,
88108                     cls: handleCls + pos,
88109                     renderTo: me.el
88110                 });
88111                 me[pos].el.unselectable();
88112                 if (me.transparent) {
88113                     me[pos].el.setOpacity(0);
88114                 }
88115             }
88116         }
88117
88118         
88119         if (Ext.isNumber(me.width)) {
88120             me.width = Ext.Number.constrain(me.width, me.minWidth, me.maxWidth);
88121         }
88122         if (Ext.isNumber(me.height)) {
88123             me.height = Ext.Number.constrain(me.height, me.minHeight, me.maxHeight);
88124         }
88125
88126         
88127         if (me.width != null || me.height != null) {
88128             if (me.originalTarget) {
88129                 me.originalTarget.setWidth(me.width);
88130                 me.originalTarget.setHeight(me.height);
88131             }
88132             me.resizeTo(me.width, me.height);
88133         }
88134
88135         me.forceHandlesHeight();
88136     },
88137
88138     disable: function() {
88139         this.resizeTracker.disable();
88140     },
88141
88142     enable: function() {
88143         this.resizeTracker.enable();
88144     },
88145
88146     
88147     onBeforeResize: function(tracker, e) {
88148         var b = this.target.getBox();
88149         return this.fireEvent('beforeresize', this, b.width, b.height, e);
88150     },
88151
88152     
88153     onResize: function(tracker, e) {
88154         var me = this,
88155             b = me.target.getBox();
88156         me.forceHandlesHeight();
88157         return me.fireEvent('resizedrag', me, b.width, b.height, e);
88158     },
88159
88160     
88161     onResizeEnd: function(tracker, e) {
88162         var me = this,
88163             b = me.target.getBox();
88164         me.forceHandlesHeight();
88165         return me.fireEvent('resize', me, b.width, b.height, e);
88166     },
88167
88168     
88169     resizeTo : function(width, height){
88170         this.target.setSize(width, height);
88171         this.fireEvent('resize', this, width, height, null);
88172     },
88173
88174     
88175     getEl : function() {
88176         return this.el;
88177     },
88178
88179     
88180     getTarget: function() {
88181         return this.target;
88182     },
88183
88184     destroy: function() {
88185         var h;
88186         for (var i = 0, l = this.handles.length; i < l; i++) {
88187             h = this[this.possiblePositions[this.handles[i]]];
88188             delete h.owner;
88189             Ext.destroy(h);
88190         }
88191     },
88192
88193     
88194     forceHandlesHeight : function() {
88195         var me = this,
88196             handle;
88197         if (Ext.isIE6) {
88198             handle = me.east;
88199             if (handle) {
88200                 handle.setHeight(me.el.getHeight());
88201             }
88202             handle = me.west;
88203             if (handle) {
88204                 handle.setHeight(me.el.getHeight());
88205             }
88206             me.el.repaint();
88207         }
88208     }
88209 });
88210
88211
88212 Ext.define('Ext.resizer.ResizeTracker', {
88213     extend: 'Ext.dd.DragTracker',
88214     dynamic: true,
88215     preserveRatio: false,
88216
88217     
88218     constrainTo: null,
88219     
88220     proxyCls:  Ext.baseCSSPrefix + 'resizable-proxy',
88221
88222     constructor: function(config) {
88223         var me = this;
88224
88225         if (!config.el) {
88226             if (config.target.isComponent) {
88227                 me.el = config.target.getEl();
88228             } else {
88229                 me.el = config.target;
88230             }
88231         }
88232         this.callParent(arguments);
88233
88234         
88235         if (me.preserveRatio && me.minWidth && me.minHeight) {
88236             var widthRatio = me.minWidth / me.el.getWidth(),
88237                 heightRatio = me.minHeight / me.el.getHeight();
88238
88239             
88240             
88241             
88242             if (heightRatio > widthRatio) {
88243                 me.minWidth = me.el.getWidth() * heightRatio;
88244             } else {
88245                 me.minHeight = me.el.getHeight() * widthRatio;
88246             }
88247         }
88248
88249         
88250         
88251         if (me.throttle) {
88252             var throttledResizeFn = Ext.Function.createThrottled(function() {
88253                     Ext.resizer.ResizeTracker.prototype.resize.apply(me, arguments);
88254                 }, me.throttle);
88255
88256             me.resize = function(box, direction, atEnd) {
88257                 if (atEnd) {
88258                     Ext.resizer.ResizeTracker.prototype.resize.apply(me, arguments);
88259                 } else {
88260                     throttledResizeFn.apply(null, arguments);
88261                 }
88262             };
88263         }
88264     },
88265
88266     onBeforeStart: function(e) {
88267         
88268         this.startBox = this.el.getBox();
88269     },
88270
88271     
88272     getDynamicTarget: function() {
88273         var me = this,
88274             target = me.target;
88275             
88276         if (me.dynamic) {
88277             return target;
88278         } else if (!me.proxy) {
88279             me.proxy = me.createProxy(target);
88280         }
88281         me.proxy.show();
88282         return me.proxy;
88283     },
88284     
88285     
88286     createProxy: function(target){
88287         var proxy,
88288             cls = this.proxyCls,
88289             renderTo;
88290             
88291         if (target.isComponent) {
88292             proxy = target.getProxy().addCls(cls);
88293         } else {
88294             renderTo = Ext.getBody();
88295             if (Ext.scopeResetCSS) {
88296                 renderTo = Ext.getBody().createChild({
88297                     cls: Ext.baseCSSPrefix + 'reset'
88298                 });
88299             }
88300             proxy = target.createProxy({
88301                 tag: 'div',
88302                 cls: cls,
88303                 id: target.id + '-rzproxy'
88304             }, renderTo);
88305         }
88306         proxy.removeCls(Ext.baseCSSPrefix + 'proxy-el');
88307         return proxy;
88308     },
88309
88310     onStart: function(e) {
88311         
88312         this.activeResizeHandle = Ext.getCmp(this.getDragTarget().id);
88313
88314         
88315         if (!this.dynamic) {
88316             this.resize(this.startBox, {
88317                 horizontal: 'none',
88318                 vertical: 'none'
88319             });
88320         }
88321     },
88322
88323     onDrag: function(e) {
88324         
88325         if (this.dynamic || this.proxy) {
88326             this.updateDimensions(e);
88327         }
88328     },
88329
88330     updateDimensions: function(e, atEnd) {
88331         var me = this,
88332             region = me.activeResizeHandle.region,
88333             offset = me.getOffset(me.constrainTo ? 'dragTarget' : null),
88334             box = me.startBox,
88335             ratio,
88336             widthAdjust = 0,
88337             heightAdjust = 0,
88338             snappedWidth,
88339             snappedHeight,
88340             adjustX = 0,
88341             adjustY = 0,
88342             dragRatio,
88343             horizDir = offset[0] < 0 ? 'right' : 'left',
88344             vertDir = offset[1] < 0 ? 'down' : 'up',
88345             oppositeCorner,
88346             axis; 
88347
88348         switch (region) {
88349             case 'south':
88350                 heightAdjust = offset[1];
88351                 axis = 2;
88352                 break;
88353             case 'north':
88354                 heightAdjust = -offset[1];
88355                 adjustY = -heightAdjust;
88356                 axis = 2;
88357                 break;
88358             case 'east':
88359                 widthAdjust = offset[0];
88360                 axis = 1;
88361                 break;
88362             case 'west':
88363                 widthAdjust = -offset[0];
88364                 adjustX = -widthAdjust;
88365                 axis = 1;
88366                 break;
88367             case 'northeast':
88368                 heightAdjust = -offset[1];
88369                 adjustY = -heightAdjust;
88370                 widthAdjust = offset[0];
88371                 oppositeCorner = [box.x, box.y + box.height];
88372                 axis = 3;
88373                 break;
88374             case 'southeast':
88375                 heightAdjust = offset[1];
88376                 widthAdjust = offset[0];
88377                 oppositeCorner = [box.x, box.y];
88378                 axis = 3;
88379                 break;
88380             case 'southwest':
88381                 widthAdjust = -offset[0];
88382                 adjustX = -widthAdjust;
88383                 heightAdjust = offset[1];
88384                 oppositeCorner = [box.x + box.width, box.y];
88385                 axis = 3;
88386                 break;
88387             case 'northwest':
88388                 heightAdjust = -offset[1];
88389                 adjustY = -heightAdjust;
88390                 widthAdjust = -offset[0];
88391                 adjustX = -widthAdjust;
88392                 oppositeCorner = [box.x + box.width, box.y + box.height];
88393                 axis = 3;
88394                 break;
88395         }
88396
88397         var newBox = {
88398             width: box.width + widthAdjust,
88399             height: box.height + heightAdjust,
88400             x: box.x + adjustX,
88401             y: box.y + adjustY
88402         };
88403
88404         
88405         snappedWidth = Ext.Number.snap(newBox.width, me.widthIncrement);
88406         snappedHeight = Ext.Number.snap(newBox.height, me.heightIncrement);
88407         if (snappedWidth != newBox.width || snappedHeight != newBox.height){
88408             switch (region) {
88409                 case 'northeast':
88410                     newBox.y -= snappedHeight - newBox.height;
88411                     break;
88412                 case 'north':
88413                     newBox.y -= snappedHeight - newBox.height;
88414                     break;
88415                 case 'southwest':
88416                     newBox.x -= snappedWidth - newBox.width;
88417                     break;
88418                 case 'west':
88419                     newBox.x -= snappedWidth - newBox.width;
88420                     break;
88421                 case 'northwest':
88422                     newBox.x -= snappedWidth - newBox.width;
88423                     newBox.y -= snappedHeight - newBox.height;
88424             }
88425             newBox.width = snappedWidth;
88426             newBox.height = snappedHeight;
88427         }
88428
88429         
88430         if (newBox.width < me.minWidth || newBox.width > me.maxWidth) {
88431             newBox.width = Ext.Number.constrain(newBox.width, me.minWidth, me.maxWidth);
88432
88433             
88434             if (adjustX) {
88435                 newBox.x = box.x + (box.width - newBox.width);
88436             }
88437         } else {
88438             me.lastX = newBox.x;
88439         }
88440         if (newBox.height < me.minHeight || newBox.height > me.maxHeight) {
88441             newBox.height = Ext.Number.constrain(newBox.height, me.minHeight, me.maxHeight);
88442
88443             
88444             if (adjustY) {
88445                 newBox.y = box.y + (box.height - newBox.height);
88446             }
88447         } else {
88448             me.lastY = newBox.y;
88449         }
88450
88451         
88452         if (me.preserveRatio || e.shiftKey) {
88453             var newHeight,
88454                 newWidth;
88455
88456             ratio = me.startBox.width / me.startBox.height;
88457
88458             
88459             newHeight = Math.min(Math.max(me.minHeight, newBox.width / ratio), me.maxHeight);
88460             newWidth = Math.min(Math.max(me.minWidth, newBox.height * ratio), me.maxWidth);
88461
88462             
88463             if (axis == 1) {
88464                 newBox.height = newHeight;
88465             }
88466
88467             
88468             else if (axis == 2) {
88469                 newBox.width = newWidth;
88470             }
88471
88472             
88473             else {
88474                 
88475                 
88476                 dragRatio = Math.abs(oppositeCorner[0] - this.lastXY[0]) / Math.abs(oppositeCorner[1] - this.lastXY[1]);
88477
88478                 
88479                 if (dragRatio > ratio) {
88480                     newBox.height = newHeight;
88481                 } else {
88482                     newBox.width = newWidth;
88483                 }
88484
88485                 
88486                 if (region == 'northeast') {
88487                     newBox.y = box.y - (newBox.height - box.height);
88488                 } else if (region == 'northwest') {
88489                     newBox.y = box.y - (newBox.height - box.height);
88490                     newBox.x = box.x - (newBox.width - box.width);
88491                 } else if (region == 'southwest') {
88492                     newBox.x = box.x - (newBox.width - box.width);
88493                 }
88494             }
88495         }
88496
88497         if (heightAdjust === 0) {
88498             vertDir = 'none';
88499         }
88500         if (widthAdjust === 0) {
88501             horizDir = 'none';
88502         }
88503         me.resize(newBox, {
88504             horizontal: horizDir,
88505             vertical: vertDir
88506         }, atEnd);
88507     },
88508
88509     getResizeTarget: function(atEnd) {
88510         return atEnd ? this.target : this.getDynamicTarget();
88511     },
88512
88513     resize: function(box, direction, atEnd) {
88514         var target = this.getResizeTarget(atEnd);
88515         if (target.isComponent) {
88516             if (target.floating) {
88517                 target.setPagePosition(box.x, box.y);
88518             }
88519             target.setSize(box.width, box.height);
88520         } else {
88521             target.setBox(box);
88522             
88523             if (this.originalTarget) {
88524                 this.originalTarget.setBox(box);
88525             }
88526         }
88527     },
88528
88529     onEnd: function(e) {
88530         this.updateDimensions(e, true);
88531         if (this.proxy) {
88532             this.proxy.hide();
88533         }
88534     }
88535 });
88536
88537
88538 Ext.define('Ext.resizer.SplitterTracker', {
88539     extend: 'Ext.dd.DragTracker',
88540     requires: ['Ext.util.Region'],
88541     enabled: true,
88542     
88543     overlayCls: Ext.baseCSSPrefix + 'resizable-overlay',
88544
88545     getPrevCmp: function() {
88546         var splitter = this.getSplitter();
88547         return splitter.previousSibling();
88548     },
88549
88550     getNextCmp: function() {
88551         var splitter = this.getSplitter();
88552         return splitter.nextSibling();
88553     },
88554
88555     
88556     
88557     onBeforeStart: function(e) {
88558         var me = this,
88559             prevCmp = me.getPrevCmp(),
88560             nextCmp = me.getNextCmp(),
88561             collapseEl = me.getSplitter().collapseEl,
88562             overlay;
88563             
88564         if (collapseEl && (e.getTarget() === me.getSplitter().collapseEl.dom)) {
88565             return false;
88566         }
88567
88568         
88569         if (nextCmp.collapsed || prevCmp.collapsed) {
88570             return false;
88571         }
88572         
88573         overlay = me.overlay =  Ext.getBody().createChild({
88574             cls: me.overlayCls, 
88575             html: '&#160;'
88576         });
88577         overlay.unselectable();
88578         overlay.setSize(Ext.Element.getViewWidth(true), Ext.Element.getViewHeight(true));
88579         overlay.show();
88580         
88581         
88582         me.prevBox  = prevCmp.getEl().getBox();
88583         me.nextBox  = nextCmp.getEl().getBox();
88584         me.constrainTo = me.calculateConstrainRegion();
88585     },
88586
88587     
88588     onStart: function(e) {
88589         var splitter = this.getSplitter();
88590         splitter.addCls(splitter.baseCls + '-active');
88591     },
88592
88593     
88594     calculateConstrainRegion: function() {
88595         var me         = this,
88596             splitter   = me.getSplitter(),
88597             splitWidth = splitter.getWidth(),
88598             defaultMin = splitter.defaultSplitMin,
88599             orient     = splitter.orientation,
88600             prevBox    = me.prevBox,
88601             prevCmp    = me.getPrevCmp(),
88602             nextBox    = me.nextBox,
88603             nextCmp    = me.getNextCmp(),
88604             
88605             
88606             
88607             prevConstrainRegion, nextConstrainRegion;
88608
88609         
88610         if (orient === 'vertical') {
88611
88612             
88613             
88614             prevConstrainRegion = Ext.create('Ext.util.Region',
88615                 prevBox.y,
88616                 
88617                 
88618                 (prevCmp.maxWidth ? prevBox.x + prevCmp.maxWidth : nextBox.right - (nextCmp.minWidth || defaultMin)) + splitWidth,
88619                 prevBox.bottom,
88620                 prevBox.x + (prevCmp.minWidth || defaultMin)
88621             );
88622             
88623             nextConstrainRegion = Ext.create('Ext.util.Region',
88624                 nextBox.y,
88625                 nextBox.right - (nextCmp.minWidth || defaultMin),
88626                 nextBox.bottom,
88627                 
88628                 
88629                 (nextCmp.maxWidth ? nextBox.right - nextCmp.maxWidth : prevBox.x + (prevBox.minWidth || defaultMin)) - splitWidth
88630             );
88631         } else {
88632             
88633             prevConstrainRegion = Ext.create('Ext.util.Region',
88634                 prevBox.y + (prevCmp.minHeight || defaultMin),
88635                 prevBox.right,
88636                 
88637                 
88638                 (prevCmp.maxHeight ? prevBox.y + prevCmp.maxHeight : nextBox.bottom - (nextCmp.minHeight || defaultMin)) + splitWidth,
88639                 prevBox.x
88640             );
88641             
88642             nextConstrainRegion = Ext.create('Ext.util.Region',
88643                 
88644                 
88645                 (nextCmp.maxHeight ? nextBox.bottom - nextCmp.maxHeight : prevBox.y + (prevCmp.minHeight || defaultMin)) - splitWidth,
88646                 nextBox.right,
88647                 nextBox.bottom - (nextCmp.minHeight || defaultMin),
88648                 nextBox.x
88649             );
88650         }
88651
88652         
88653         return prevConstrainRegion.intersect(nextConstrainRegion);
88654     },
88655
88656     
88657     performResize: function(e) {
88658         var me       = this,
88659             offset   = me.getOffset('dragTarget'),
88660             splitter = me.getSplitter(),
88661             orient   = splitter.orientation,
88662             prevCmp  = me.getPrevCmp(),
88663             nextCmp  = me.getNextCmp(),
88664             owner    = splitter.ownerCt,
88665             layout   = owner.getLayout();
88666
88667         
88668         owner.suspendLayout = true;
88669
88670         if (orient === 'vertical') {
88671             if (prevCmp) {
88672                 if (!prevCmp.maintainFlex) {
88673                     delete prevCmp.flex;
88674                     prevCmp.setSize(me.prevBox.width + offset[0], prevCmp.getHeight());
88675                 }
88676             }
88677             if (nextCmp) {
88678                 if (!nextCmp.maintainFlex) {
88679                     delete nextCmp.flex;
88680                     nextCmp.setSize(me.nextBox.width - offset[0], nextCmp.getHeight());
88681                 }
88682             }
88683         
88684         } else {
88685             if (prevCmp) {
88686                 if (!prevCmp.maintainFlex) {
88687                     delete prevCmp.flex;
88688                     prevCmp.setSize(prevCmp.getWidth(), me.prevBox.height + offset[1]);
88689                 }
88690             }
88691             if (nextCmp) {
88692                 if (!nextCmp.maintainFlex) {
88693                     delete nextCmp.flex;
88694                     nextCmp.setSize(prevCmp.getWidth(), me.nextBox.height - offset[1]);
88695                 }
88696             }
88697         }
88698         delete owner.suspendLayout;
88699         layout.onLayout();
88700     },
88701
88702     
88703     
88704     
88705     endDrag: function () {
88706         var me = this;
88707
88708         if (me.overlay) {
88709              me.overlay.remove();
88710              delete me.overlay;
88711         }
88712
88713         me.callParent(arguments); 
88714     },
88715
88716     
88717     onEnd: function(e) {
88718         var me = this,
88719             splitter = me.getSplitter();
88720             
88721         splitter.removeCls(splitter.baseCls + '-active');
88722         me.performResize();
88723     },
88724
88725     
88726     
88727     onDrag: function(e) {
88728         var me        = this,
88729             offset    = me.getOffset('dragTarget'),
88730             splitter  = me.getSplitter(),
88731             splitEl   = splitter.getEl(),
88732             orient    = splitter.orientation;
88733
88734         if (orient === "vertical") {
88735             splitEl.setX(me.startRegion.left + offset[0]);
88736         } else {
88737             splitEl.setY(me.startRegion.top + offset[1]);
88738         }
88739     },
88740
88741     getSplitter: function() {
88742         return Ext.getCmp(this.getDragCt().id);
88743     }
88744 });
88745
88746 Ext.define('Ext.selection.CellModel', {
88747     extend: 'Ext.selection.Model',
88748     alias: 'selection.cellmodel',
88749     requires: ['Ext.util.KeyNav'],
88750
88751     
88752     enableKeyNav: true,
88753
88754     
88755     preventWrap: false,
88756
88757     constructor: function(){
88758         this.addEvents(
88759             
88760             'deselect',
88761
88762             
88763             'select'
88764         );
88765         this.callParent(arguments);
88766     },
88767
88768     bindComponent: function(view) {
88769         var me = this;
88770         me.primaryView = view;
88771         me.views = me.views || [];
88772         me.views.push(view);
88773         me.bind(view.getStore(), true);
88774
88775         view.on({
88776             cellmousedown: me.onMouseDown,
88777             refresh: me.onViewRefresh,
88778             scope: me
88779         });
88780
88781         if (me.enableKeyNav) {
88782             me.initKeyNav(view);
88783         }
88784     },
88785
88786     initKeyNav: function(view) {
88787         var me = this;
88788
88789         if (!view.rendered) {
88790             view.on('render', Ext.Function.bind(me.initKeyNav, me, [view], 0), me, {single: true});
88791             return;
88792         }
88793
88794         view.el.set({
88795             tabIndex: -1
88796         });
88797
88798         
88799         
88800         me.keyNav = Ext.create('Ext.util.KeyNav', view.el, {
88801             up: me.onKeyUp,
88802             down: me.onKeyDown,
88803             right: me.onKeyRight,
88804             left: me.onKeyLeft,
88805             tab: me.onKeyTab,
88806             scope: me
88807         });
88808     },
88809
88810     getHeaderCt: function() {
88811         return this.primaryView.headerCt;
88812     },
88813
88814     onKeyUp: function(e, t) {
88815         this.move('up', e);
88816     },
88817
88818     onKeyDown: function(e, t) {
88819         this.move('down', e);
88820     },
88821
88822     onKeyLeft: function(e, t) {
88823         this.move('left', e);
88824     },
88825
88826     onKeyRight: function(e, t) {
88827         this.move('right', e);
88828     },
88829
88830     move: function(dir, e) {
88831         var me = this,
88832             pos = me.primaryView.walkCells(me.getCurrentPosition(), dir, e, me.preventWrap);
88833         if (pos) {
88834             me.setCurrentPosition(pos);
88835         }
88836         return pos;
88837     },
88838
88839     
88840     getCurrentPosition: function() {
88841         return this.position;
88842     },
88843
88844     
88845     setCurrentPosition: function(pos) {
88846         var me = this;
88847
88848         if (me.position) {
88849             me.onCellDeselect(me.position);
88850         }
88851         if (pos) {
88852             me.onCellSelect(pos);
88853         }
88854         me.position = pos;
88855     },
88856
88857     
88858     onMouseDown: function(view, cell, cellIndex, record, row, rowIndex, e) {
88859         this.setCurrentPosition({
88860             row: rowIndex,
88861             column: cellIndex
88862         });
88863     },
88864
88865     
88866     
88867     onCellSelect: function(position) {
88868         var me = this,
88869             store = me.view.getStore(),
88870             record = store.getAt(position.row);
88871
88872         me.doSelect(record);
88873         me.primaryView.onCellSelect(position);
88874         
88875         me.primaryView.onCellFocus(position);
88876         me.fireEvent('select', me, record, position.row, position.column);
88877     },
88878
88879     
88880     
88881     onCellDeselect: function(position) {
88882         var me = this,
88883             store = me.view.getStore(),
88884             record = store.getAt(position.row);
88885
88886         me.doDeselect(record);
88887         me.primaryView.onCellDeselect(position);
88888         me.fireEvent('deselect', me, record, position.row, position.column);
88889     },
88890
88891     onKeyTab: function(e, t) {
88892         var me = this,
88893             direction = e.shiftKey ? 'left' : 'right',
88894             editingPlugin = me.view.editingPlugin,
88895             position = me.move(direction, e);
88896
88897         if (editingPlugin && position && me.wasEditing) {
88898             editingPlugin.startEditByPosition(position);
88899         }
88900         delete me.wasEditing;
88901     },
88902
88903     onEditorTab: function(editingPlugin, e) {
88904         var me = this,
88905             direction = e.shiftKey ? 'left' : 'right',
88906             position  = me.move(direction, e);
88907
88908         if (position) {
88909             editingPlugin.startEditByPosition(position);
88910             me.wasEditing = true;
88911         }
88912     },
88913
88914     refresh: function() {
88915         var pos = this.getCurrentPosition();
88916         if (pos) {
88917             this.onCellSelect(pos);
88918         }
88919     },
88920
88921     onViewRefresh: function() {
88922         var pos = this.getCurrentPosition();
88923         if (pos) {
88924             this.onCellDeselect(pos);
88925             this.setCurrentPosition(null);
88926         }
88927     },
88928
88929     selectByPosition: function(position) {
88930         this.setCurrentPosition(position);
88931     }
88932 });
88933
88934 Ext.define('Ext.selection.RowModel', {
88935     extend: 'Ext.selection.Model',
88936     alias: 'selection.rowmodel',
88937     requires: ['Ext.util.KeyNav'],
88938
88939     
88940     deltaScroll: 5,
88941
88942     
88943     enableKeyNav: true,
88944     
88945     
88946     ignoreRightMouseSelection: true,
88947
88948     constructor: function(){
88949         this.addEvents(
88950             
88951             'beforedeselect',
88952
88953             
88954             'beforeselect',
88955
88956             
88957             'deselect',
88958
88959             
88960             'select'
88961         );
88962         this.callParent(arguments);
88963     },
88964
88965     bindComponent: function(view) {
88966         var me = this;
88967
88968         me.views = me.views || [];
88969         me.views.push(view);
88970         me.bind(view.getStore(), true);
88971
88972         view.on({
88973             itemmousedown: me.onRowMouseDown,
88974             scope: me
88975         });
88976
88977         if (me.enableKeyNav) {
88978             me.initKeyNav(view);
88979         }
88980     },
88981
88982     initKeyNav: function(view) {
88983         var me = this;
88984
88985         if (!view.rendered) {
88986             view.on('render', Ext.Function.bind(me.initKeyNav, me, [view], 0), me, {single: true});
88987             return;
88988         }
88989
88990         view.el.set({
88991             tabIndex: -1
88992         });
88993
88994         
88995         
88996         me.keyNav = new Ext.util.KeyNav(view.el, {
88997             up: me.onKeyUp,
88998             down: me.onKeyDown,
88999             right: me.onKeyRight,
89000             left: me.onKeyLeft,
89001             pageDown: me.onKeyPageDown,
89002             pageUp: me.onKeyPageUp,
89003             home: me.onKeyHome,
89004             end: me.onKeyEnd,
89005             scope: me
89006         });
89007         view.el.on(Ext.EventManager.getKeyEvent(), me.onKeyPress, me);
89008     },
89009
89010     
89011     
89012     
89013     getRowsVisible: function() {
89014         var rowsVisible = false,
89015             view = this.views[0],
89016             row = view.getNode(0),
89017             rowHeight, gridViewHeight;
89018
89019         if (row) {
89020             rowHeight = Ext.fly(row).getHeight();
89021             gridViewHeight = view.el.getHeight();
89022             rowsVisible = Math.floor(gridViewHeight / rowHeight);
89023         }
89024
89025         return rowsVisible;
89026     },
89027
89028     
89029     onKeyEnd: function(e, t) {
89030         var me = this,
89031             last = me.store.getAt(me.store.getCount() - 1);
89032
89033         if (last) {
89034             if (e.shiftKey) {
89035                 me.selectRange(last, me.lastFocused || 0);
89036                 me.setLastFocused(last);
89037             } else if (e.ctrlKey) {
89038                 me.setLastFocused(last);
89039             } else {
89040                 me.doSelect(last);
89041             }
89042         }
89043     },
89044
89045     
89046     onKeyHome: function(e, t) {
89047         var me = this,
89048             first = me.store.getAt(0);
89049
89050         if (first) {
89051             if (e.shiftKey) {
89052                 me.selectRange(first, me.lastFocused || 0);
89053                 me.setLastFocused(first);
89054             } else if (e.ctrlKey) {
89055                 me.setLastFocused(first);
89056             } else {
89057                 me.doSelect(first, false);
89058             }
89059         }
89060     },
89061
89062     
89063     onKeyPageUp: function(e, t) {
89064         var me = this,
89065             rowsVisible = me.getRowsVisible(),
89066             selIdx,
89067             prevIdx,
89068             prevRecord,
89069             currRec;
89070
89071         if (rowsVisible) {
89072             selIdx = me.lastFocused ? me.store.indexOf(me.lastFocused) : 0;
89073             prevIdx = selIdx - rowsVisible;
89074             if (prevIdx < 0) {
89075                 prevIdx = 0;
89076             }
89077             prevRecord = me.store.getAt(prevIdx);
89078             if (e.shiftKey) {
89079                 currRec = me.store.getAt(selIdx);
89080                 me.selectRange(prevRecord, currRec, e.ctrlKey, 'up');
89081                 me.setLastFocused(prevRecord);
89082             } else if (e.ctrlKey) {
89083                 e.preventDefault();
89084                 me.setLastFocused(prevRecord);
89085             } else {
89086                 me.doSelect(prevRecord);
89087             }
89088
89089         }
89090     },
89091
89092     
89093     onKeyPageDown: function(e, t) {
89094         var me = this,
89095             rowsVisible = me.getRowsVisible(),
89096             selIdx,
89097             nextIdx,
89098             nextRecord,
89099             currRec;
89100
89101         if (rowsVisible) {
89102             selIdx = me.lastFocused ? me.store.indexOf(me.lastFocused) : 0;
89103             nextIdx = selIdx + rowsVisible;
89104             if (nextIdx >= me.store.getCount()) {
89105                 nextIdx = me.store.getCount() - 1;
89106             }
89107             nextRecord = me.store.getAt(nextIdx);
89108             if (e.shiftKey) {
89109                 currRec = me.store.getAt(selIdx);
89110                 me.selectRange(nextRecord, currRec, e.ctrlKey, 'down');
89111                 me.setLastFocused(nextRecord);
89112             } else if (e.ctrlKey) {
89113                 
89114                 
89115                 e.preventDefault();
89116                 me.setLastFocused(nextRecord);
89117             } else {
89118                 me.doSelect(nextRecord);
89119             }
89120         }
89121     },
89122
89123     
89124     
89125     onKeyPress: function(e, t) {
89126         if (e.getKey() === e.SPACE) {
89127             e.stopEvent();
89128             var me = this,
89129                 record = me.lastFocused;
89130
89131             if (record) {
89132                 if (me.isSelected(record)) {
89133                     me.doDeselect(record, false);
89134                 } else {
89135                     me.doSelect(record, true);
89136                 }
89137             }
89138         }
89139     },
89140
89141     
89142     
89143     
89144     onKeyUp: function(e, t) {
89145         var me = this,
89146             view = me.views[0],
89147             idx  = me.store.indexOf(me.lastFocused),
89148             record;
89149
89150         if (idx > 0) {
89151             
89152             
89153             record = me.store.getAt(idx - 1);
89154             if (e.shiftKey && me.lastFocused) {
89155                 if (me.isSelected(me.lastFocused) && me.isSelected(record)) {
89156                     me.doDeselect(me.lastFocused, true);
89157                     me.setLastFocused(record);
89158                 } else if (!me.isSelected(me.lastFocused)) {
89159                     me.doSelect(me.lastFocused, true);
89160                     me.doSelect(record, true);
89161                 } else {
89162                     me.doSelect(record, true);
89163                 }
89164             } else if (e.ctrlKey) {
89165                 me.setLastFocused(record);
89166             } else {
89167                 me.doSelect(record);
89168                 
89169             }
89170         }
89171         
89172         
89173         
89174         
89175         
89176         
89177         
89178     },
89179
89180     
89181     
89182     
89183     onKeyDown: function(e, t) {
89184         var me = this,
89185             view = me.views[0],
89186             idx  = me.store.indexOf(me.lastFocused),
89187             record;
89188
89189         
89190         
89191         if (idx + 1 < me.store.getCount()) {
89192             record = me.store.getAt(idx + 1);
89193             if (me.selected.getCount() === 0) {
89194                 me.doSelect(record);
89195                 
89196             } else if (e.shiftKey && me.lastFocused) {
89197                 if (me.isSelected(me.lastFocused) && me.isSelected(record)) {
89198                     me.doDeselect(me.lastFocused, true);
89199                     me.setLastFocused(record);
89200                 } else if (!me.isSelected(me.lastFocused)) {
89201                     me.doSelect(me.lastFocused, true);
89202                     me.doSelect(record, true);
89203                 } else {
89204                     me.doSelect(record, true);
89205                 }
89206             } else if (e.ctrlKey) {
89207                 me.setLastFocused(record);
89208             } else {
89209                 me.doSelect(record);
89210                 
89211             }
89212         }
89213     },
89214
89215     scrollByDeltaX: function(delta) {
89216         var view    = this.views[0],
89217             section = view.up(),
89218             hScroll = section.horizontalScroller;
89219
89220         if (hScroll) {
89221             hScroll.scrollByDeltaX(delta);
89222         }
89223     },
89224
89225     onKeyLeft: function(e, t) {
89226         this.scrollByDeltaX(-this.deltaScroll);
89227     },
89228
89229     onKeyRight: function(e, t) {
89230         this.scrollByDeltaX(this.deltaScroll);
89231     },
89232
89233     
89234     
89235     onRowMouseDown: function(view, record, item, index, e) {
89236         view.el.focus();
89237         if (!this.allowRightMouseSelection(e)) {
89238             return;
89239         }
89240         this.selectWithEvent(record, e);
89241     },
89242     
89243     
89244     allowRightMouseSelection: function(e) {
89245         var disallow = this.ignoreRightMouseSelection && e.button !== 0;
89246         if (disallow) {
89247             disallow = this.hasSelection();
89248         }
89249         return !disallow;
89250     },
89251
89252     
89253     
89254     onSelectChange: function(record, isSelected, suppressEvent, commitFn) {
89255         var me      = this,
89256             views   = me.views,
89257             viewsLn = views.length,
89258             store   = me.store,
89259             rowIdx  = store.indexOf(record),
89260             eventName = isSelected ? 'select' : 'deselect',
89261             i = 0;
89262
89263         if ((suppressEvent || me.fireEvent('before' + eventName, me, record, rowIdx)) !== false &&
89264                 commitFn() !== false) {
89265
89266             for (; i < viewsLn; i++) {
89267                 if (isSelected) {
89268                     views[i].onRowSelect(rowIdx, suppressEvent);
89269                 } else {
89270                     views[i].onRowDeselect(rowIdx, suppressEvent);
89271                 }
89272             }
89273
89274             if (!suppressEvent) {
89275                 me.fireEvent(eventName, me, record, rowIdx);
89276             }
89277         }
89278     },
89279
89280     
89281     
89282     onLastFocusChanged: function(oldFocused, newFocused, supressFocus) {
89283         var views   = this.views,
89284             viewsLn = views.length,
89285             store   = this.store,
89286             rowIdx,
89287             i = 0;
89288
89289         if (oldFocused) {
89290             rowIdx = store.indexOf(oldFocused);
89291             if (rowIdx != -1) {
89292                 for (; i < viewsLn; i++) {
89293                     views[i].onRowFocus(rowIdx, false);
89294                 }
89295             }
89296         }
89297
89298         if (newFocused) {
89299             rowIdx = store.indexOf(newFocused);
89300             if (rowIdx != -1) {
89301                 for (i = 0; i < viewsLn; i++) {
89302                     views[i].onRowFocus(rowIdx, true, supressFocus);
89303                 }
89304             }
89305         }
89306     },
89307
89308     onEditorTab: function(editingPlugin, e) {
89309         var me = this,
89310             view = me.views[0],
89311             record = editingPlugin.getActiveRecord(),
89312             header = editingPlugin.getActiveColumn(),
89313             position = view.getPosition(record, header),
89314             direction = e.shiftKey ? 'left' : 'right',
89315             newPosition  = view.walkCells(position, direction, e, this.preventWrap);
89316
89317         if (newPosition) {
89318             editingPlugin.startEditByPosition(newPosition);
89319         }
89320     },
89321
89322     selectByPosition: function(position) {
89323         var record = this.store.getAt(position.row);
89324         this.select(record);
89325     }
89326 });
89327
89328 Ext.define('Ext.selection.CheckboxModel', {
89329     alias: 'selection.checkboxmodel',
89330     extend: 'Ext.selection.RowModel',
89331
89332     
89333     mode: 'MULTI',
89334
89335     
89336     injectCheckbox: 0,
89337
89338     
89339     checkOnly: false,
89340
89341     headerWidth: 24,
89342
89343     
89344     checkerOnCls: Ext.baseCSSPrefix + 'grid-hd-checker-on',
89345
89346     bindComponent: function(view) {
89347         var me = this;
89348
89349         me.sortable = false;
89350         me.callParent(arguments);
89351         if (!me.hasLockedHeader() || view.headerCt.lockedCt) {
89352             
89353             view.headerCt.on('headerclick', me.onHeaderClick, me);
89354             me.addCheckbox(true);
89355             me.mon(view.ownerCt, 'reconfigure', me.addCheckbox, me);
89356         }
89357     },
89358
89359     hasLockedHeader: function(){
89360         var hasLocked = false;
89361         Ext.each(this.views, function(view){
89362             if (view.headerCt.lockedCt) {
89363                 hasLocked = true;
89364                 return false;
89365             }
89366         });
89367         return hasLocked;
89368     },
89369
89370     
89371     addCheckbox: function(initial){
89372         var me = this,
89373             checkbox = me.injectCheckbox,
89374             view = me.views[0],
89375             headerCt = view.headerCt;
89376
89377         if (checkbox !== false) {
89378             if (checkbox == 'first') {
89379                 checkbox = 0;
89380             } else if (checkbox == 'last') {
89381                 checkbox = headerCt.getColumnCount();
89382             }
89383             headerCt.add(checkbox,  me.getHeaderConfig());
89384         }
89385
89386         if (initial !== true) {
89387             view.refresh();
89388         }
89389     },
89390
89391     
89392     toggleUiHeader: function(isChecked) {
89393         var view     = this.views[0],
89394             headerCt = view.headerCt,
89395             checkHd  = headerCt.child('gridcolumn[isCheckerHd]');
89396
89397         if (checkHd) {
89398             if (isChecked) {
89399                 checkHd.el.addCls(this.checkerOnCls);
89400             } else {
89401                 checkHd.el.removeCls(this.checkerOnCls);
89402             }
89403         }
89404     },
89405
89406     
89407     onHeaderClick: function(headerCt, header, e) {
89408         if (header.isCheckerHd) {
89409             e.stopEvent();
89410             var isChecked = header.el.hasCls(Ext.baseCSSPrefix + 'grid-hd-checker-on');
89411             if (isChecked) {
89412                 
89413                 this.deselectAll(true);
89414             } else {
89415                 
89416                 this.selectAll(true);
89417             }
89418         }
89419     },
89420
89421     
89422     getHeaderConfig: function() {
89423         var me = this;
89424
89425         return {
89426             isCheckerHd: true,
89427             text : '&#160;',
89428             width: me.headerWidth,
89429             sortable: false,
89430             draggable: false,
89431             resizable: false,
89432             hideable: false,
89433             menuDisabled: true,
89434             dataIndex: '',
89435             cls: Ext.baseCSSPrefix + 'column-header-checkbox ',
89436             renderer: Ext.Function.bind(me.renderer, me),
89437             locked: me.hasLockedHeader()
89438         };
89439     },
89440
89441     
89442     renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
89443         metaData.tdCls = Ext.baseCSSPrefix + 'grid-cell-special';
89444         return '<div class="' + Ext.baseCSSPrefix + 'grid-row-checker">&#160;</div>';
89445     },
89446
89447     
89448     onRowMouseDown: function(view, record, item, index, e) {
89449         view.el.focus();
89450         var me = this,
89451             checker = e.getTarget('.' + Ext.baseCSSPrefix + 'grid-row-checker');
89452             
89453         if (!me.allowRightMouseSelection(e)) {
89454             return;
89455         }
89456
89457         
89458         if (me.checkOnly && !checker) {
89459             return;
89460         }
89461
89462         if (checker) {
89463             var mode = me.getSelectionMode();
89464             
89465             
89466             if (mode !== 'SINGLE') {
89467                 me.setSelectionMode('SIMPLE');
89468             }
89469             me.selectWithEvent(record, e);
89470             me.setSelectionMode(mode);
89471         } else {
89472             me.selectWithEvent(record, e);
89473         }
89474     },
89475
89476     
89477     onSelectChange: function() {
89478         this.callParent(arguments);
89479
89480         
89481         var hdSelectStatus = this.selected.getCount() === this.store.getCount();
89482         this.toggleUiHeader(hdSelectStatus);
89483     }
89484 });
89485
89486
89487 Ext.define('Ext.selection.TreeModel', {
89488     extend: 'Ext.selection.RowModel',
89489     alias: 'selection.treemodel',
89490     
89491     
89492     
89493     
89494     pruneRemoved: false,
89495     
89496     onKeyRight: function(e, t) {
89497         var focused = this.getLastFocused(),
89498             view    = this.view;
89499             
89500         if (focused) {
89501             
89502             
89503             
89504             if (focused.isExpanded()) {
89505                 this.onKeyDown(e, t);
89506             
89507             } else if (!focused.isLeaf()) {
89508                 view.expand(focused);
89509             }
89510         }
89511     },
89512     
89513     onKeyLeft: function(e, t) {
89514         var focused = this.getLastFocused(),
89515             view    = this.view,
89516             viewSm  = view.getSelectionModel(),
89517             parentNode, parentRecord;
89518
89519         if (focused) {
89520             parentNode = focused.parentNode;
89521             
89522             if (focused.isExpanded()) {
89523                 view.collapse(focused);
89524             
89525             
89526             } else if (parentNode && !parentNode.isRoot()) {
89527                 
89528                 if (e.shiftKey) {
89529                     viewSm.selectRange(parentNode, focused, e.ctrlKey, 'up');
89530                     viewSm.setLastFocused(parentNode);
89531                 
89532                 } else if (e.ctrlKey) {
89533                     viewSm.setLastFocused(parentNode);
89534                 
89535                 } else {
89536                     viewSm.select(parentNode);
89537                 }
89538             }
89539         }
89540     },
89541     
89542     onKeyPress: function(e, t) {
89543         var key = e.getKey(),
89544             selected, 
89545             checked;
89546         
89547         if (key === e.SPACE || key === e.ENTER) {
89548             e.stopEvent();
89549             selected = this.getLastSelected();
89550             if (selected) {
89551                 this.view.onCheckChange(selected);
89552             }
89553         } else {
89554             this.callParent(arguments);
89555         }
89556     }
89557 });
89558
89559
89560 Ext.define('Ext.slider.Thumb', {
89561     requires: ['Ext.dd.DragTracker', 'Ext.util.Format'],
89562     
89563     topZIndex: 10000,
89564
89565     
89566
89567     
89568     constructor: function(config) {
89569         var me = this;
89570
89571         
89572         Ext.apply(me, config || {}, {
89573             cls: Ext.baseCSSPrefix + 'slider-thumb',
89574
89575             
89576             constrain: false
89577         });
89578         me.callParent([config]);
89579
89580         if (me.slider.vertical) {
89581             Ext.apply(me, Ext.slider.Thumb.Vertical);
89582         }
89583     },
89584
89585     
89586     render: function() {
89587         var me = this;
89588
89589         me.el = me.slider.innerEl.insertFirst({cls: me.cls});
89590         if (me.disabled) {
89591             me.disable();
89592         }
89593         me.initEvents();
89594     },
89595
89596     
89597     move: function(v, animate){
89598         if(!animate){
89599             this.el.setLeft(v);
89600         }else{
89601             Ext.create('Ext.fx.Anim', {
89602                 target: this.el,
89603                 duration: 350,
89604                 to: {
89605                     left: v
89606                 }
89607             });
89608         }
89609     },
89610
89611     
89612     bringToFront: function() {
89613         this.el.setStyle('zIndex', this.topZIndex);
89614     },
89615
89616     
89617     sendToBack: function() {
89618         this.el.setStyle('zIndex', '');
89619     },
89620
89621     
89622     enable: function() {
89623         var me = this;
89624
89625         me.disabled = false;
89626         if (me.el) {
89627             me.el.removeCls(me.slider.disabledCls);
89628         }
89629     },
89630
89631     
89632     disable: function() {
89633         var me = this;
89634
89635         me.disabled = true;
89636         if (me.el) {
89637             me.el.addCls(me.slider.disabledCls);
89638         }
89639     },
89640
89641     
89642     initEvents: function() {
89643         var me = this,
89644             el = me.el;
89645
89646         me.tracker = Ext.create('Ext.dd.DragTracker', {
89647             onBeforeStart: Ext.Function.bind(me.onBeforeDragStart, me),
89648             onStart      : Ext.Function.bind(me.onDragStart, me),
89649             onDrag       : Ext.Function.bind(me.onDrag, me),
89650             onEnd        : Ext.Function.bind(me.onDragEnd, me),
89651             tolerance    : 3,
89652             autoStart    : 300,
89653             overCls      : Ext.baseCSSPrefix + 'slider-thumb-over'
89654         });
89655
89656         me.tracker.initEl(el);
89657     },
89658
89659     
89660     onBeforeDragStart : function(e) {
89661         if (this.disabled) {
89662             return false;
89663         } else {
89664             this.slider.promoteThumb(this);
89665             return true;
89666         }
89667     },
89668
89669     
89670     onDragStart: function(e){
89671         var me = this;
89672
89673         me.el.addCls(Ext.baseCSSPrefix + 'slider-thumb-drag');
89674         me.dragging = true;
89675         me.dragStartValue = me.value;
89676
89677         me.slider.fireEvent('dragstart', me.slider, e, me);
89678     },
89679
89680     
89681     onDrag: function(e) {
89682         var me       = this,
89683             slider   = me.slider,
89684             index    = me.index,
89685             newValue = me.getNewValue(),
89686             above,
89687             below;
89688
89689         if (me.constrain) {
89690             above = slider.thumbs[index + 1];
89691             below = slider.thumbs[index - 1];
89692
89693             if (below !== undefined && newValue <= below.value) {
89694                 newValue = below.value;
89695             }
89696
89697             if (above !== undefined && newValue >= above.value) {
89698                 newValue = above.value;
89699             }
89700         }
89701
89702         slider.setValue(index, newValue, false);
89703         slider.fireEvent('drag', slider, e, me);
89704     },
89705
89706     getNewValue: function() {
89707         var slider = this.slider,
89708             pos = slider.innerEl.translatePoints(this.tracker.getXY());
89709
89710         return Ext.util.Format.round(slider.reverseValue(pos.left), slider.decimalPrecision);
89711     },
89712
89713     
89714     onDragEnd: function(e) {
89715         var me     = this,
89716             slider = me.slider,
89717             value  = me.value;
89718
89719         me.el.removeCls(Ext.baseCSSPrefix + 'slider-thumb-drag');
89720
89721         me.dragging = false;
89722         slider.fireEvent('dragend', slider, e);
89723
89724         if (me.dragStartValue != value) {
89725             slider.fireEvent('changecomplete', slider, value, me);
89726         }
89727     },
89728
89729     destroy: function() {
89730         Ext.destroy(this.tracker);
89731     },
89732     statics: {
89733         
89734         Vertical: {
89735             getNewValue: function() {
89736                 var slider   = this.slider,
89737                     innerEl  = slider.innerEl,
89738                     pos      = innerEl.translatePoints(this.tracker.getXY()),
89739                     bottom   = innerEl.getHeight() - pos.top;
89740
89741                 return Ext.util.Format.round(slider.reverseValue(bottom), slider.decimalPrecision);
89742             },
89743             move: function(v, animate) {
89744                 if (!animate) {
89745                     this.el.setBottom(v);
89746                 } else {
89747                     Ext.create('Ext.fx.Anim', {
89748                         target: this.el,
89749                         duration: 350,
89750                         to: {
89751                             bottom: v
89752                         }
89753                     });
89754                 }
89755             }
89756         }
89757     }
89758 });
89759
89760
89761 Ext.define('Ext.slider.Tip', {
89762     extend: 'Ext.tip.Tip',
89763     minWidth: 10,
89764     alias: 'widget.slidertip',
89765     offsets : [0, -10],
89766
89767     isSliderTip: true,
89768
89769     init: function(slider) {
89770         var me = this;
89771
89772         slider.on({
89773             scope    : me,
89774             dragstart: me.onSlide,
89775             drag     : me.onSlide,
89776             dragend  : me.hide,
89777             destroy  : me.destroy
89778         });
89779     },
89780     
89781     onSlide : function(slider, e, thumb) {
89782         var me = this;
89783         me.show();
89784         me.update(me.getText(thumb));
89785         me.doComponentLayout();
89786         me.el.alignTo(thumb.el, 'b-t?', me.offsets);
89787     },
89788
89789     
89790     getText : function(thumb) {
89791         return String(thumb.value);
89792     }
89793 });
89794
89795 Ext.define('Ext.slider.Multi', {
89796     extend: 'Ext.form.field.Base',
89797     alias: 'widget.multislider',
89798     alternateClassName: 'Ext.slider.MultiSlider',
89799
89800     requires: [
89801         'Ext.slider.Thumb',
89802         'Ext.slider.Tip',
89803         'Ext.Number',
89804         'Ext.util.Format',
89805         'Ext.Template',
89806         'Ext.layout.component.field.Slider'
89807     ],
89808
89809     
89810     fieldSubTpl: [
89811         '<div id="{id}" class="' + Ext.baseCSSPrefix + 'slider {fieldCls} {vertical}" aria-valuemin="{minValue}" aria-valuemax="{maxValue}" aria-valuenow="{value}" aria-valuetext="{value}">',
89812             '<div id="{cmpId}-endEl" class="' + Ext.baseCSSPrefix + 'slider-end" role="presentation">',
89813                 '<div id="{cmpId}-innerEl" class="' + Ext.baseCSSPrefix + 'slider-inner" role="presentation">',
89814                     '<a id="{cmpId}-focusEl" class="' + Ext.baseCSSPrefix + 'slider-focus" href="#" tabIndex="-1" hidefocus="on" role="presentation"></a>',
89815                 '</div>',
89816             '</div>',
89817         '</div>',
89818         {
89819             disableFormats: true,
89820             compiled: true
89821         }
89822     ],
89823
89824     
89825
89826     
89827
89828     
89829     vertical: false,
89830
89831     
89832     minValue: 0,
89833
89834     
89835     maxValue: 100,
89836
89837     
89838     decimalPrecision: 0,
89839
89840     
89841     keyIncrement: 1,
89842
89843     
89844     increment: 0,
89845
89846     
89847     clickRange: [5,15],
89848
89849     
89850     clickToChange : true,
89851
89852     
89853     animate: true,
89854
89855     
89856     dragging: false,
89857
89858     
89859     constrainThumbs: true,
89860
89861     componentLayout: 'sliderfield',
89862
89863     
89864     useTips : true,
89865
89866     
89867     tipText : null,
89868
89869     ariaRole: 'slider',
89870
89871     
89872     initValue: function() {
89873         var me = this,
89874             extValue = Ext.value,
89875             
89876             values = extValue(me.values, [extValue(me.value, extValue(me.minValue, 0))]),
89877             i = 0,
89878             len = values.length;
89879
89880         
89881         me.originalValue = values;
89882
89883         
89884         for (; i < len; i++) {
89885             me.addThumb(values[i]);
89886         }
89887     },
89888
89889     
89890     initComponent : function() {
89891         var me = this,
89892             tipPlug,
89893             hasTip;
89894
89895         
89896         me.thumbs = [];
89897
89898         me.keyIncrement = Math.max(me.increment, me.keyIncrement);
89899
89900         me.addEvents(
89901             
89902             'beforechange',
89903
89904             
89905             'change',
89906
89907             
89908             'changecomplete',
89909
89910             
89911             'dragstart',
89912
89913             
89914             'drag',
89915
89916             
89917             'dragend'
89918         );
89919
89920         if (me.vertical) {
89921             Ext.apply(me, Ext.slider.Multi.Vertical);
89922         }
89923
89924         me.callParent();
89925
89926         
89927         if (me.useTips) {
89928             tipPlug = me.tipText ? {getText: me.tipText} : {};
89929             me.plugins = me.plugins || [];
89930             Ext.each(me.plugins, function(plug){
89931                 if (plug.isSliderTip) {
89932                     hasTip = true;
89933                     return false;
89934                 }
89935             });
89936             if (!hasTip) {
89937                 me.plugins.push(Ext.create('Ext.slider.Tip', tipPlug));
89938             }
89939         }
89940     },
89941
89942     
89943     addThumb: function(value) {
89944         var me = this,
89945             thumb = Ext.create('Ext.slider.Thumb', {
89946             value    : value,
89947             slider   : me,
89948             index    : me.thumbs.length,
89949             constrain: me.constrainThumbs
89950         });
89951         me.thumbs.push(thumb);
89952
89953         
89954         if (me.rendered) {
89955             thumb.render();
89956         }
89957
89958         return thumb;
89959     },
89960
89961     
89962     promoteThumb: function(topThumb) {
89963         var thumbs = this.thumbs,
89964             ln = thumbs.length,
89965             zIndex, thumb, i;
89966
89967         for (i = 0; i < ln; i++) {
89968             thumb = thumbs[i];
89969
89970             if (thumb == topThumb) {
89971                 thumb.bringToFront();
89972             } else {
89973                 thumb.sendToBack();
89974             }
89975         }
89976     },
89977
89978     
89979     onRender : function() {
89980         var me = this,
89981             i = 0,
89982             thumbs = me.thumbs,
89983             len = thumbs.length,
89984             thumb;
89985
89986         Ext.applyIf(me.subTplData, {
89987             vertical: me.vertical ? Ext.baseCSSPrefix + 'slider-vert' : Ext.baseCSSPrefix + 'slider-horz',
89988             minValue: me.minValue,
89989             maxValue: me.maxValue,
89990             value: me.value
89991         });
89992
89993         me.addChildEls('endEl', 'innerEl', 'focusEl');
89994
89995         me.callParent(arguments);
89996
89997         
89998         for (; i < len; i++) {
89999             thumbs[i].render();
90000         }
90001
90002         
90003         thumb = me.innerEl.down('.' + Ext.baseCSSPrefix + 'slider-thumb');
90004         me.halfThumb = (me.vertical ? thumb.getHeight() : thumb.getWidth()) / 2;
90005
90006     },
90007
90008     
90009     onChange : function(slider, v) {
90010         this.setValue(v, undefined, true);
90011     },
90012
90013     
90014     initEvents : function() {
90015         var me = this;
90016
90017         me.mon(me.el, {
90018             scope    : me,
90019             mousedown: me.onMouseDown,
90020             keydown  : me.onKeyDown,
90021             change : me.onChange
90022         });
90023
90024         me.focusEl.swallowEvent("click", true);
90025     },
90026
90027     
90028     onMouseDown : function(e) {
90029         var me = this,
90030             thumbClicked = false,
90031             i = 0,
90032             thumbs = me.thumbs,
90033             len = thumbs.length,
90034             local;
90035
90036         if (me.disabled) {
90037             return;
90038         }
90039
90040         
90041         for (; i < len; i++) {
90042             thumbClicked = thumbClicked || e.target == thumbs[i].el.dom;
90043         }
90044
90045         if (me.clickToChange && !thumbClicked) {
90046             local = me.innerEl.translatePoints(e.getXY());
90047             me.onClickChange(local);
90048         }
90049         me.focus();
90050     },
90051
90052     
90053     onClickChange : function(local) {
90054         var me = this,
90055             thumb, index;
90056
90057         if (local.top > me.clickRange[0] && local.top < me.clickRange[1]) {
90058             
90059             thumb = me.getNearest(local, 'left');
90060             if (!thumb.disabled) {
90061                 index = thumb.index;
90062                 me.setValue(index, Ext.util.Format.round(me.reverseValue(local.left), me.decimalPrecision), undefined, true);
90063             }
90064         }
90065     },
90066
90067     
90068     getNearest: function(local, prop) {
90069         var me = this,
90070             localValue = prop == 'top' ? me.innerEl.getHeight() - local[prop] : local[prop],
90071             clickValue = me.reverseValue(localValue),
90072             nearestDistance = (me.maxValue - me.minValue) + 5, 
90073             index = 0,
90074             nearest = null,
90075             thumbs = me.thumbs,
90076             i = 0,
90077             len = thumbs.length,
90078             thumb,
90079             value,
90080             dist;
90081
90082         for (; i < len; i++) {
90083             thumb = me.thumbs[i];
90084             value = thumb.value;
90085             dist  = Math.abs(value - clickValue);
90086
90087             if (Math.abs(dist <= nearestDistance)) {
90088                 nearest = thumb;
90089                 index = i;
90090                 nearestDistance = dist;
90091             }
90092         }
90093         return nearest;
90094     },
90095
90096     
90097     onKeyDown : function(e) {
90098         
90099         var me = this,
90100             k,
90101             val;
90102
90103         if(me.disabled || me.thumbs.length !== 1) {
90104             e.preventDefault();
90105             return;
90106         }
90107         k = e.getKey();
90108
90109         switch(k) {
90110             case e.UP:
90111             case e.RIGHT:
90112                 e.stopEvent();
90113                 val = e.ctrlKey ? me.maxValue : me.getValue(0) + me.keyIncrement;
90114                 me.setValue(0, val, undefined, true);
90115             break;
90116             case e.DOWN:
90117             case e.LEFT:
90118                 e.stopEvent();
90119                 val = e.ctrlKey ? me.minValue : me.getValue(0) - me.keyIncrement;
90120                 me.setValue(0, val, undefined, true);
90121             break;
90122             default:
90123                 e.preventDefault();
90124         }
90125     },
90126
90127     
90128     afterRender : function() {
90129         var me = this,
90130             i = 0,
90131             thumbs = me.thumbs,
90132             len = thumbs.length,
90133             thumb,
90134             v;
90135
90136         me.callParent(arguments);
90137
90138         for (; i < len; i++) {
90139             thumb = thumbs[i];
90140
90141             if (thumb.value !== undefined) {
90142                 v = me.normalizeValue(thumb.value);
90143                 if (v !== thumb.value) {
90144                     
90145                     me.setValue(i, v, false);
90146                 } else {
90147                     thumb.move(me.translateValue(v), false);
90148                 }
90149             }
90150         }
90151     },
90152
90153     
90154     getRatio : function() {
90155         var w = this.innerEl.getWidth(),
90156             v = this.maxValue - this.minValue;
90157         return v === 0 ? w : (w/v);
90158     },
90159
90160     
90161     normalizeValue : function(v) {
90162         var me = this;
90163
90164         v = Ext.Number.snap(v, this.increment, this.minValue, this.maxValue);
90165         v = Ext.util.Format.round(v, me.decimalPrecision);
90166         v = Ext.Number.constrain(v, me.minValue, me.maxValue);
90167         return v;
90168     },
90169
90170     
90171     setMinValue : function(val) {
90172         var me = this,
90173             i = 0,
90174             thumbs = me.thumbs,
90175             len = thumbs.length,
90176             t;
90177
90178         me.minValue = val;
90179         if (me.rendered) {
90180             me.inputEl.dom.setAttribute('aria-valuemin', val);
90181         }
90182
90183         for (; i < len; ++i) {
90184             t = thumbs[i];
90185             t.value = t.value < val ? val : t.value;
90186         }
90187         me.syncThumbs();
90188     },
90189
90190     
90191     setMaxValue : function(val) {
90192         var me = this,
90193             i = 0,
90194             thumbs = me.thumbs,
90195             len = thumbs.length,
90196             t;
90197
90198         me.maxValue = val;
90199         if (me.rendered) {
90200             me.inputEl.dom.setAttribute('aria-valuemax', val);
90201         }
90202
90203         for (; i < len; ++i) {
90204             t = thumbs[i];
90205             t.value = t.value > val ? val : t.value;
90206         }
90207         me.syncThumbs();
90208     },
90209
90210     
90211     setValue : function(index, value, animate, changeComplete) {
90212         var me = this,
90213             thumb = me.thumbs[index];
90214
90215         
90216         value = me.normalizeValue(value);
90217
90218         if (value !== thumb.value && me.fireEvent('beforechange', me, value, thumb.value, thumb) !== false) {
90219             thumb.value = value;
90220             if (me.rendered) {
90221                 
90222                 
90223                 me.inputEl.set({
90224                     'aria-valuenow': value,
90225                     'aria-valuetext': value
90226                 });
90227
90228                 thumb.move(me.translateValue(value), Ext.isDefined(animate) ? animate !== false : me.animate);
90229
90230                 me.fireEvent('change', me, value, thumb);
90231                 if (changeComplete) {
90232                     me.fireEvent('changecomplete', me, value, thumb);
90233                 }
90234             }
90235         }
90236     },
90237
90238     
90239     translateValue : function(v) {
90240         var ratio = this.getRatio();
90241         return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
90242     },
90243
90244     
90245     reverseValue : function(pos) {
90246         var ratio = this.getRatio();
90247         return (pos + (this.minValue * ratio)) / ratio;
90248     },
90249
90250     
90251     focus : function() {
90252         this.focusEl.focus(10);
90253     },
90254
90255     
90256     onDisable: function() {
90257         var me = this,
90258             i = 0,
90259             thumbs = me.thumbs,
90260             len = thumbs.length,
90261             thumb,
90262             el,
90263             xy;
90264
90265         me.callParent();
90266
90267         for (; i < len; i++) {
90268             thumb = thumbs[i];
90269             el = thumb.el;
90270
90271             thumb.disable();
90272
90273             if(Ext.isIE) {
90274                 
90275                 
90276                 xy = el.getXY();
90277                 el.hide();
90278
90279                 me.innerEl.addCls(me.disabledCls).dom.disabled = true;
90280
90281                 if (!me.thumbHolder) {
90282                     me.thumbHolder = me.endEl.createChild({cls: Ext.baseCSSPrefix + 'slider-thumb ' + me.disabledCls});
90283                 }
90284
90285                 me.thumbHolder.show().setXY(xy);
90286             }
90287         }
90288     },
90289
90290     
90291     onEnable: function() {
90292         var me = this,
90293             i = 0,
90294             thumbs = me.thumbs,
90295             len = thumbs.length,
90296             thumb,
90297             el;
90298
90299         this.callParent();
90300
90301         for (; i < len; i++) {
90302             thumb = thumbs[i];
90303             el = thumb.el;
90304
90305             thumb.enable();
90306
90307             if (Ext.isIE) {
90308                 me.innerEl.removeCls(me.disabledCls).dom.disabled = false;
90309
90310                 if (me.thumbHolder) {
90311                     me.thumbHolder.hide();
90312                 }
90313
90314                 el.show();
90315                 me.syncThumbs();
90316             }
90317         }
90318     },
90319
90320     
90321     syncThumbs : function() {
90322         if (this.rendered) {
90323             var thumbs = this.thumbs,
90324                 length = thumbs.length,
90325                 i = 0;
90326
90327             for (; i < length; i++) {
90328                 thumbs[i].move(this.translateValue(thumbs[i].value));
90329             }
90330         }
90331     },
90332
90333     
90334     getValue : function(index) {
90335         return Ext.isNumber(index) ? this.thumbs[index].value : this.getValues();
90336     },
90337
90338     
90339     getValues: function() {
90340         var values = [],
90341             i = 0,
90342             thumbs = this.thumbs,
90343             len = thumbs.length;
90344
90345         for (; i < len; i++) {
90346             values.push(thumbs[i].value);
90347         }
90348
90349         return values;
90350     },
90351
90352     getSubmitValue: function() {
90353         var me = this;
90354         return (me.disabled || !me.submitValue) ? null : me.getValue();
90355     },
90356
90357     reset: function() {
90358         var me = this,
90359             Array = Ext.Array;
90360         Array.forEach(Array.from(me.originalValue), function(val, i) {
90361             me.setValue(i, val);
90362         });
90363         me.clearInvalid();
90364         
90365         delete me.wasValid;
90366     },
90367
90368     
90369     beforeDestroy : function() {
90370         var me = this;
90371
90372         Ext.destroy(me.innerEl, me.endEl, me.focusEl);
90373         Ext.each(me.thumbs, function(thumb) {
90374             Ext.destroy(thumb);
90375         }, me);
90376
90377         me.callParent();
90378     },
90379
90380     statics: {
90381         
90382         Vertical: {
90383             getRatio : function() {
90384                 var h = this.innerEl.getHeight(),
90385                     v = this.maxValue - this.minValue;
90386                 return h/v;
90387             },
90388
90389             onClickChange : function(local) {
90390                 var me = this,
90391                     thumb, index, bottom;
90392
90393                 if (local.left > me.clickRange[0] && local.left < me.clickRange[1]) {
90394                     thumb = me.getNearest(local, 'top');
90395                     if (!thumb.disabled) {
90396                         index = thumb.index;
90397                         bottom =  me.reverseValue(me.innerEl.getHeight() - local.top);
90398
90399                         me.setValue(index, Ext.util.Format.round(me.minValue + bottom, me.decimalPrecision), undefined, true);
90400                     }
90401                 }
90402             }
90403         }
90404     }
90405 });
90406
90407
90408 Ext.define('Ext.slider.Single', {
90409     extend: 'Ext.slider.Multi',
90410     alias: ['widget.slider', 'widget.sliderfield'],
90411     alternateClassName: ['Ext.Slider', 'Ext.form.SliderField', 'Ext.slider.SingleSlider', 'Ext.slider.Slider'],
90412
90413     
90414     getValue: function() {
90415         
90416         return this.callParent([0]);
90417     },
90418
90419     
90420     setValue: function(value, animate) {
90421         var args = Ext.toArray(arguments),
90422             len  = args.length;
90423
90424         
90425         
90426         
90427         if (len == 1 || (len <= 3 && typeof arguments[1] != 'number')) {
90428             args.unshift(0);
90429         }
90430
90431         return this.callParent(args);
90432     },
90433
90434     
90435     getNearest : function(){
90436         
90437         return this.thumbs[0];
90438     }
90439 });
90440
90441
90442 Ext.define('Ext.tab.Tab', {
90443     extend: 'Ext.button.Button',
90444     alias: 'widget.tab',
90445
90446     requires: [
90447         'Ext.layout.component.Tab',
90448         'Ext.util.KeyNav'
90449     ],
90450
90451     componentLayout: 'tab',
90452
90453     isTab: true,
90454
90455     baseCls: Ext.baseCSSPrefix + 'tab',
90456
90457     
90458     activeCls: 'active',
90459
90460     
90461
90462     
90463     closableCls: 'closable',
90464
90465     
90466     closable: true,
90467
90468     
90469     closeText: 'Close Tab',
90470
90471     
90472     active: false,
90473
90474     
90475
90476     scale: false,
90477
90478     position: 'top',
90479
90480     initComponent: function() {
90481         var me = this;
90482
90483         me.addEvents(
90484             
90485             'activate',
90486
90487             
90488             'deactivate',
90489
90490             
90491             'beforeclose',
90492
90493             
90494             'close'
90495         );
90496
90497         me.callParent(arguments);
90498
90499         if (me.card) {
90500             me.setCard(me.card);
90501         }
90502     },
90503
90504     
90505     onRender: function() {
90506         var me = this,
90507             tabBar = me.up('tabbar'),
90508             tabPanel = me.up('tabpanel');
90509
90510         me.addClsWithUI(me.position);
90511
90512         
90513         
90514
90515         me.syncClosableUI();
90516
90517         
90518         if (!me.minWidth) {
90519             me.minWidth = (tabBar) ? tabBar.minTabWidth : me.minWidth;
90520             if (!me.minWidth && tabPanel) {
90521                 me.minWidth = tabPanel.minTabWidth;
90522             }
90523             if (me.minWidth && me.iconCls) {
90524                 me.minWidth += 25;
90525             }
90526         }
90527         if (!me.maxWidth) {
90528             me.maxWidth = (tabBar) ? tabBar.maxTabWidth : me.maxWidth;
90529             if (!me.maxWidth && tabPanel) {
90530                 me.maxWidth = tabPanel.maxTabWidth;
90531             }
90532         }
90533
90534         me.callParent(arguments);
90535
90536         if (me.active) {
90537             me.activate(true);
90538         }
90539
90540         me.syncClosableElements();
90541
90542         me.keyNav = Ext.create('Ext.util.KeyNav', me.el, {
90543             enter: me.onEnterKey,
90544             del: me.onDeleteKey,
90545             scope: me
90546         });
90547     },
90548
90549     
90550     enable : function(silent) {
90551         var me = this;
90552
90553         me.callParent(arguments);
90554
90555         me.removeClsWithUI(me.position + '-disabled');
90556
90557         return me;
90558     },
90559
90560     
90561     disable : function(silent) {
90562         var me = this;
90563
90564         me.callParent(arguments);
90565
90566         me.addClsWithUI(me.position + '-disabled');
90567
90568         return me;
90569     },
90570
90571     
90572     onDestroy: function() {
90573         var me = this;
90574
90575         if (me.closeEl) {
90576             me.closeEl.un('click', Ext.EventManager.preventDefault);
90577             me.closeEl = null;
90578         }
90579
90580         Ext.destroy(me.keyNav);
90581         delete me.keyNav;
90582
90583         me.callParent(arguments);
90584     },
90585
90586     
90587     setClosable: function(closable) {
90588         var me = this;
90589
90590         
90591         closable = (!arguments.length || !!closable);
90592
90593         if (me.closable != closable) {
90594             me.closable = closable;
90595
90596             
90597             if (me.card) {
90598                 me.card.closable = closable;
90599             }
90600
90601             me.syncClosableUI();
90602
90603             if (me.rendered) {
90604                 me.syncClosableElements();
90605
90606                 
90607                 me.doComponentLayout();
90608                 if (me.ownerCt) {
90609                     me.ownerCt.doLayout();
90610                 }
90611             }
90612         }
90613     },
90614
90615     
90616     syncClosableElements: function () {
90617         var me = this;
90618
90619         if (me.closable) {
90620             if (!me.closeEl) {
90621                 me.closeEl = me.el.createChild({
90622                     tag: 'a',
90623                     cls: me.baseCls + '-close-btn',
90624                     href: '#',
90625                     
90626                     title: me.closeText
90627                 }).on('click', Ext.EventManager.preventDefault);  
90628             }
90629         } else {
90630             var closeEl = me.closeEl;
90631             if (closeEl) {
90632                 closeEl.un('click', Ext.EventManager.preventDefault);
90633                 closeEl.remove();
90634                 me.closeEl = null;
90635             }
90636         }
90637     },
90638
90639     
90640     syncClosableUI: function () {
90641         var me = this, classes = [me.closableCls, me.closableCls + '-' + me.position];
90642
90643         if (me.closable) {
90644             me.addClsWithUI(classes);
90645         } else {
90646             me.removeClsWithUI(classes);
90647         }
90648     },
90649
90650     
90651     setCard: function(card) {
90652         var me = this;
90653
90654         me.card = card;
90655         me.setText(me.title || card.title);
90656         me.setIconCls(me.iconCls || card.iconCls);
90657     },
90658
90659     
90660     onCloseClick: function() {
90661         var me = this;
90662
90663         if (me.fireEvent('beforeclose', me) !== false) {
90664             if (me.tabBar) {
90665                 if (me.tabBar.closeTab(me) === false) {
90666                     
90667                     return;
90668                 }
90669             } else {
90670                 
90671                 me.fireEvent('close', me);
90672             }
90673         }
90674     },
90675
90676     
90677     fireClose: function(){
90678         this.fireEvent('close', this);
90679     },
90680
90681     
90682     onEnterKey: function(e) {
90683         var me = this;
90684
90685         if (me.tabBar) {
90686             me.tabBar.onClick(e, me.el);
90687         }
90688     },
90689
90690    
90691     onDeleteKey: function(e) {
90692         var me = this;
90693
90694         if (me.closable) {
90695             me.onCloseClick();
90696         }
90697     },
90698
90699     
90700     activate : function(supressEvent) {
90701         var me = this;
90702
90703         me.active = true;
90704         me.addClsWithUI([me.activeCls, me.position + '-' + me.activeCls]);
90705
90706         if (supressEvent !== true) {
90707             me.fireEvent('activate', me);
90708         }
90709     },
90710
90711     
90712     deactivate : function(supressEvent) {
90713         var me = this;
90714
90715         me.active = false;
90716         me.removeClsWithUI([me.activeCls, me.position + '-' + me.activeCls]);
90717
90718         if (supressEvent !== true) {
90719             me.fireEvent('deactivate', me);
90720         }
90721     }
90722 });
90723
90724
90725 Ext.define('Ext.tab.Bar', {
90726     extend: 'Ext.panel.Header',
90727     alias: 'widget.tabbar',
90728     baseCls: Ext.baseCSSPrefix + 'tab-bar',
90729
90730     requires: [
90731         'Ext.tab.Tab',
90732         'Ext.FocusManager'
90733     ],
90734
90735     isTabBar: true,
90736     
90737     
90738     
90739     
90740
90741     
90742     defaultType: 'tab',
90743
90744     
90745     plain: false,
90746
90747     
90748     renderTpl: [
90749         '<div id="{id}-body" class="{baseCls}-body <tpl if="bodyCls"> {bodyCls}</tpl> <tpl if="ui"> {baseCls}-body-{ui}<tpl for="uiCls"> {parent.baseCls}-body-{parent.ui}-{.}</tpl></tpl>"<tpl if="bodyStyle"> style="{bodyStyle}"</tpl>></div>',
90750         '<div id="{id}-strip" class="{baseCls}-strip<tpl if="ui"> {baseCls}-strip-{ui}<tpl for="uiCls"> {parent.baseCls}-strip-{parent.ui}-{.}</tpl></tpl>"></div>'
90751     ],
90752
90753     
90754
90755     
90756
90757     
90758     initComponent: function() {
90759         var me = this,
90760             keys;
90761
90762         if (me.plain) {
90763             me.setUI(me.ui + '-plain');
90764         }
90765
90766         me.addClsWithUI(me.dock);
90767
90768         me.addEvents(
90769             
90770             'change'
90771         );
90772
90773         me.addChildEls('body', 'strip');
90774         me.callParent(arguments);
90775
90776         
90777         me.layout.align = (me.orientation == 'vertical') ? 'left' : 'top';
90778         me.layout.overflowHandler = Ext.create('Ext.layout.container.boxOverflow.Scroller', me.layout);
90779
90780         me.remove(me.titleCmp);
90781         delete me.titleCmp;
90782
90783         
90784         keys = me.orientation == 'vertical' ? ['up', 'down'] : ['left', 'right'];
90785         Ext.FocusManager.subscribe(me, {
90786             keys: keys
90787         });
90788
90789         Ext.apply(me.renderData, {
90790             bodyCls: me.bodyCls
90791         });
90792     },
90793
90794     
90795     onAdd: function(tab) {
90796         tab.position = this.dock;
90797         this.callParent(arguments);
90798     },
90799     
90800     onRemove: function(tab) {
90801         var me = this;
90802         
90803         if (tab === me.previousTab) {
90804             me.previousTab = null;
90805         }
90806         if (me.items.getCount() === 0) {
90807             me.activeTab = null;
90808         }
90809         me.callParent(arguments);    
90810     },
90811
90812     
90813     afterRender: function() {
90814         var me = this;
90815
90816         me.mon(me.el, {
90817             scope: me,
90818             click: me.onClick,
90819             delegate: '.' + Ext.baseCSSPrefix + 'tab'
90820         });
90821         me.callParent(arguments);
90822
90823     },
90824
90825     afterComponentLayout : function() {
90826         var me = this;
90827
90828         me.callParent(arguments);
90829         me.strip.setWidth(me.el.getWidth());
90830     },
90831
90832     
90833     onClick: function(e, target) {
90834         
90835         var tab = Ext.getCmp(target.id),
90836             tabPanel = this.tabPanel;
90837
90838         target = e.getTarget();
90839
90840         if (tab && tab.isDisabled && !tab.isDisabled()) {
90841             if (tab.closable && target === tab.closeEl.dom) {
90842                 tab.onCloseClick();
90843             } else {
90844                 if (tabPanel) {
90845                     
90846                     tabPanel.setActiveTab(tab.card);
90847                 } else {
90848                     this.setActiveTab(tab);
90849                 }
90850                 tab.focus();
90851             }
90852         }
90853     },
90854
90855     
90856     closeTab: function(tab) {
90857         var me = this,
90858             card = tab.card,
90859             tabPanel = me.tabPanel,
90860             nextTab;
90861
90862         if (card && card.fireEvent('beforeclose', card) === false) {
90863             return false;
90864         }
90865
90866         if (tab.active && me.items.getCount() > 1) {
90867             nextTab = me.previousTab || tab.next('tab') || me.items.first();
90868             me.setActiveTab(nextTab);
90869             if (tabPanel) {
90870                 tabPanel.setActiveTab(nextTab.card);
90871             }
90872         }
90873         
90874         tab.fireClose();
90875         me.remove(tab);
90876
90877         if (tabPanel && card) {
90878             card.fireEvent('close', card);
90879             tabPanel.remove(card);
90880         }
90881
90882         if (nextTab) {
90883             nextTab.focus();
90884         }
90885     },
90886
90887     
90888     setActiveTab: function(tab) {
90889         if (tab.disabled) {
90890             return;
90891         }
90892         var me = this;
90893         if (me.activeTab) {
90894             me.previousTab = me.activeTab;
90895             me.activeTab.deactivate();
90896         }
90897         tab.activate();
90898
90899         if (me.rendered) {
90900             me.layout.layout();
90901             tab.el && tab.el.scrollIntoView(me.layout.getRenderTarget());
90902         }
90903         me.activeTab = tab;
90904         me.fireEvent('change', me, tab, tab.card);
90905     }
90906 });
90907
90908
90909 Ext.define('Ext.tab.Panel', {
90910     extend: 'Ext.panel.Panel',
90911     alias: 'widget.tabpanel',
90912     alternateClassName: ['Ext.TabPanel'],
90913
90914     requires: ['Ext.layout.container.Card', 'Ext.tab.Bar'],
90915
90916     
90917     tabPosition : 'top',
90918
90919     
90920
90921     
90922
90923     
90924
90925     
90926
90927     
90928     removePanelHeader: true,
90929
90930     
90931     plain: false,
90932
90933     
90934     itemCls: 'x-tabpanel-child',
90935
90936     
90937     minTabWidth: undefined,
90938
90939     
90940     maxTabWidth: undefined,
90941
90942     
90943     deferredRender : true,
90944
90945     
90946     initComponent: function() {
90947         var me = this,
90948             dockedItems = me.dockedItems || [],
90949             activeTab = me.activeTab || 0;
90950
90951         me.layout = Ext.create('Ext.layout.container.Card', Ext.apply({
90952             owner: me,
90953             deferredRender: me.deferredRender,
90954             itemCls: me.itemCls
90955         }, me.layout));
90956
90957         
90958         me.tabBar = Ext.create('Ext.tab.Bar', Ext.apply({}, me.tabBar, {
90959             dock: me.tabPosition,
90960             plain: me.plain,
90961             border: me.border,
90962             cardLayout: me.layout,
90963             tabPanel: me
90964         }));
90965
90966         if (dockedItems && !Ext.isArray(dockedItems)) {
90967             dockedItems = [dockedItems];
90968         }
90969
90970         dockedItems.push(me.tabBar);
90971         me.dockedItems = dockedItems;
90972
90973         me.addEvents(
90974             
90975             'beforetabchange',
90976
90977             
90978             'tabchange'
90979         );
90980         me.callParent(arguments);
90981
90982         
90983         me.setActiveTab(activeTab);
90984         
90985         me.on('afterlayout', me.afterInitialLayout, me, {single: true});
90986     },
90987
90988     
90989     afterInitialLayout: function() {
90990         var me = this,
90991             card = me.getComponent(me.activeTab);
90992
90993         if (card) {
90994             me.layout.setActiveItem(card);
90995         }
90996     },
90997
90998     
90999     setActiveTab: function(card) {
91000         var me = this,
91001             previous;
91002
91003         card = me.getComponent(card);
91004         if (card) {
91005             previous = me.getActiveTab();
91006
91007             if (previous && previous !== card && me.fireEvent('beforetabchange', me, card, previous) === false) {
91008                 return false;
91009             }
91010
91011             me.tabBar.setActiveTab(card.tab);
91012             me.activeTab = card;
91013             if (me.rendered) {
91014                 me.layout.setActiveItem(card);
91015             }
91016
91017             if (previous && previous !== card) {
91018                 me.fireEvent('tabchange', me, card, previous);
91019             }
91020         }
91021     },
91022
91023     
91024     getActiveTab: function() {
91025         return this.activeTab;
91026     },
91027
91028     
91029     getTabBar: function() {
91030         return this.tabBar;
91031     },
91032
91033     
91034     onAdd: function(item, index) {
91035         var me = this,
91036             cfg = item.tabConfig || {},
91037             defaultConfig = {
91038                 xtype: 'tab',
91039                 card: item,
91040                 disabled: item.disabled,
91041                 closable: item.closable,
91042                 hidden: item.hidden,
91043                 tabBar: me.tabBar
91044             };
91045
91046         if (item.closeText) {
91047             defaultConfig.closeText = item.closeText;
91048         }
91049         cfg = Ext.applyIf(cfg, defaultConfig);
91050         item.tab = me.tabBar.insert(index, cfg);
91051
91052         item.on({
91053             scope : me,
91054             enable: me.onItemEnable,
91055             disable: me.onItemDisable,
91056             beforeshow: me.onItemBeforeShow,
91057             iconchange: me.onItemIconChange,
91058             titlechange: me.onItemTitleChange
91059         });
91060
91061         if (item.isPanel) {
91062             if (me.removePanelHeader) {
91063                 item.preventHeader = true;
91064                 if (item.rendered) {
91065                     item.updateHeader();
91066                 }
91067             }
91068             if (item.isPanel && me.border) {
91069                 item.setBorder(false);
91070             }
91071         }
91072
91073         
91074         if (this.rendered && me.items.getCount() === 1) {
91075             me.setActiveTab(0);
91076         }
91077     },
91078
91079     
91080     onItemEnable: function(item){
91081         item.tab.enable();
91082     },
91083
91084     
91085     onItemDisable: function(item){
91086         item.tab.disable();
91087     },
91088
91089     
91090     onItemBeforeShow: function(item) {
91091         if (item !== this.activeTab) {
91092             this.setActiveTab(item);
91093             return false;
91094         }
91095     },
91096
91097     
91098     onItemIconChange: function(item, newIconCls) {
91099         item.tab.setIconCls(newIconCls);
91100         this.getTabBar().doLayout();
91101     },
91102
91103     
91104     onItemTitleChange: function(item, newTitle) {
91105         item.tab.setText(newTitle);
91106         this.getTabBar().doLayout();
91107     },
91108
91109
91110     
91111     doRemove: function(item, autoDestroy) {
91112         var me = this,
91113             items = me.items,
91114             
91115             
91116             
91117             hasItemsLeft = items.getCount() > 1;
91118
91119         if (me.destroying || !hasItemsLeft) {
91120             me.activeTab = null;
91121         } else if (item === me.activeTab) {
91122              me.setActiveTab(item.next() || items.getAt(0));
91123         }
91124         me.callParent(arguments);
91125
91126         
91127         delete item.tab.card;
91128         delete item.tab;
91129     },
91130
91131     
91132     onRemove: function(item, autoDestroy) {
91133         var me = this;
91134
91135         item.un({
91136             scope : me,
91137             enable: me.onItemEnable,
91138             disable: me.onItemDisable,
91139             beforeshow: me.onItemBeforeShow
91140         });
91141         if (!me.destroying && item.tab.ownerCt == me.tabBar) {
91142             me.tabBar.remove(item.tab);
91143         }
91144     }
91145 });
91146
91147
91148 Ext.define('Ext.toolbar.Spacer', {
91149     extend: 'Ext.Component',
91150     alias: 'widget.tbspacer',
91151     alternateClassName: 'Ext.Toolbar.Spacer',
91152     baseCls: Ext.baseCSSPrefix + 'toolbar-spacer',
91153     focusable: false
91154 });
91155
91156 Ext.define('Ext.tree.Column', {
91157     extend: 'Ext.grid.column.Column',
91158     alias: 'widget.treecolumn',
91159
91160     initComponent: function() {
91161         var origRenderer = this.renderer || this.defaultRenderer,
91162             origScope    = this.scope || window;
91163
91164         this.renderer = function(value, metaData, record, rowIdx, colIdx, store, view) {
91165             var buf   = [],
91166                 format = Ext.String.format,
91167                 depth = record.getDepth(),
91168                 treePrefix  = Ext.baseCSSPrefix + 'tree-',
91169                 elbowPrefix = treePrefix + 'elbow-',
91170                 expanderCls = treePrefix + 'expander',
91171                 imgText     = '<img src="{1}" class="{0}" />',
91172                 checkboxText= '<input type="button" role="checkbox" class="{0}" {1} />',
91173                 formattedValue = origRenderer.apply(origScope, arguments),
91174                 href = record.get('href'),
91175                 target = record.get('hrefTarget'),
91176                 cls = record.get('cls');
91177
91178             while (record) {
91179                 if (!record.isRoot() || (record.isRoot() && view.rootVisible)) {
91180                     if (record.getDepth() === depth) {
91181                         buf.unshift(format(imgText,
91182                             treePrefix + 'icon ' + 
91183                             treePrefix + 'icon' + (record.get('icon') ? '-inline ' : (record.isLeaf() ? '-leaf ' : '-parent ')) +
91184                             (record.get('iconCls') || ''),
91185                             record.get('icon') || Ext.BLANK_IMAGE_URL
91186                         ));
91187                         if (record.get('checked') !== null) {
91188                             buf.unshift(format(
91189                                 checkboxText,
91190                                 (treePrefix + 'checkbox') + (record.get('checked') ? ' ' + treePrefix + 'checkbox-checked' : ''),
91191                                 record.get('checked') ? 'aria-checked="true"' : ''
91192                             ));
91193                             if (record.get('checked')) {
91194                                 metaData.tdCls += (' ' + treePrefix + 'checked');
91195                             }
91196                         }
91197                         if (record.isLast()) {
91198                             if (record.isExpandable()) {
91199                                 buf.unshift(format(imgText, (elbowPrefix + 'end-plus ' + expanderCls), Ext.BLANK_IMAGE_URL));
91200                             } else {
91201                                 buf.unshift(format(imgText, (elbowPrefix + 'end'), Ext.BLANK_IMAGE_URL));
91202                             }
91203                             
91204                         } else {
91205                             if (record.isExpandable()) {
91206                                 buf.unshift(format(imgText, (elbowPrefix + 'plus ' + expanderCls), Ext.BLANK_IMAGE_URL));
91207                             } else {
91208                                 buf.unshift(format(imgText, (treePrefix + 'elbow'), Ext.BLANK_IMAGE_URL));
91209                             }
91210                         }
91211                     } else {
91212                         if (record.isLast() || record.getDepth() === 0) {
91213                             buf.unshift(format(imgText, (elbowPrefix + 'empty'), Ext.BLANK_IMAGE_URL));
91214                         } else if (record.getDepth() !== 0) {
91215                             buf.unshift(format(imgText, (elbowPrefix + 'line'), Ext.BLANK_IMAGE_URL));
91216                         }                      
91217                     }
91218                 }
91219                 record = record.parentNode;
91220             }
91221             if (href) {
91222                 buf.push('<a href="', href, '" target="', target, '">', formattedValue, '</a>');
91223             } else {
91224                 buf.push(formattedValue);
91225             }
91226             if (cls) {
91227                 metaData.tdCls += ' ' + cls;
91228             }
91229             return buf.join('');
91230         };
91231         this.callParent(arguments);
91232     },
91233
91234     defaultRenderer: function(value) {
91235         return value;
91236     }
91237 });
91238
91239 Ext.define('Ext.tree.View', {
91240     extend: 'Ext.view.Table',
91241     alias: 'widget.treeview',
91242
91243     loadingCls: Ext.baseCSSPrefix + 'grid-tree-loading',
91244     expandedCls: Ext.baseCSSPrefix + 'grid-tree-node-expanded',
91245
91246     expanderSelector: '.' + Ext.baseCSSPrefix + 'tree-expander',
91247     checkboxSelector: '.' + Ext.baseCSSPrefix + 'tree-checkbox',
91248     expanderIconOverCls: Ext.baseCSSPrefix + 'tree-expander-over',
91249
91250     
91251     
91252     
91253     nodeAnimWrapCls: Ext.baseCSSPrefix + 'tree-animator-wrap',
91254
91255     blockRefresh: true,
91256
91257     
91258     rootVisible: true,
91259
91260     
91261
91262     expandDuration: 250,
91263     collapseDuration: 250,
91264     
91265     toggleOnDblClick: true,
91266
91267     initComponent: function() {
91268         var me = this;
91269         
91270         if (me.initialConfig.animate === undefined) {
91271             me.animate = Ext.enableFx;
91272         }
91273         
91274         me.store = Ext.create('Ext.data.NodeStore', {
91275             recursive: true,
91276             rootVisible: me.rootVisible,
91277             listeners: {
91278                 beforeexpand: me.onBeforeExpand,
91279                 expand: me.onExpand,
91280                 beforecollapse: me.onBeforeCollapse,
91281                 collapse: me.onCollapse,
91282                 scope: me
91283             }
91284         });
91285         
91286         if (me.node) {
91287             me.setRootNode(me.node);
91288         }
91289         me.animQueue = {};
91290         me.callParent(arguments);
91291     },
91292
91293     processUIEvent: function(e) {
91294         
91295         
91296         
91297         if (e.getTarget('.' + this.nodeAnimWrapCls, this.el)) {
91298             return false;
91299         }
91300         return this.callParent(arguments);
91301     },
91302
91303     onClear: function(){
91304         this.store.removeAll();    
91305     },
91306
91307     setRootNode: function(node) {
91308         var me = this;        
91309         me.store.setNode(node);
91310         me.node = node;
91311         if (!me.rootVisible) {
91312             node.expand();
91313         }
91314     },
91315     
91316     onRender: function() {
91317         var me = this,
91318             el;
91319
91320         me.callParent(arguments);
91321
91322         el = me.el;
91323         el.on({
91324             scope: me,
91325             delegate: me.expanderSelector,
91326             mouseover: me.onExpanderMouseOver,
91327             mouseout: me.onExpanderMouseOut
91328         });
91329         el.on({
91330             scope: me,
91331             delegate: me.checkboxSelector,
91332             click: me.onCheckboxChange
91333         });
91334     },
91335
91336     onCheckboxChange: function(e, t) {
91337         var me = this,
91338             item = e.getTarget(me.getItemSelector(), me.getTargetEl());
91339             
91340         if (item) {
91341             me.onCheckChange(me.getRecord(item));
91342         }
91343     },
91344     
91345     onCheckChange: function(record){
91346         var checked = record.get('checked');
91347         if (Ext.isBoolean(checked)) {
91348             checked = !checked;
91349             record.set('checked', checked);
91350             this.fireEvent('checkchange', record, checked);
91351         }
91352     },
91353
91354     getChecked: function() {
91355         var checked = [];
91356         this.node.cascadeBy(function(rec){
91357             if (rec.get('checked')) {
91358                 checked.push(rec);
91359             }
91360         });
91361         return checked;
91362     },
91363     
91364     isItemChecked: function(rec){
91365         return rec.get('checked');
91366     },
91367
91368     createAnimWrap: function(record, index) {
91369         var thHtml = '',
91370             headerCt = this.panel.headerCt,
91371             headers = headerCt.getGridColumns(),
91372             i = 0, len = headers.length, item,
91373             node = this.getNode(record),
91374             tmpEl, nodeEl;
91375
91376         for (; i < len; i++) {
91377             item = headers[i];
91378             thHtml += '<th style="width: ' + (item.hidden ? 0 : item.getDesiredWidth()) + 'px; height: 0px;"></th>';
91379         }
91380
91381         nodeEl = Ext.get(node);        
91382         tmpEl = nodeEl.insertSibling({
91383             tag: 'tr',
91384             html: [
91385                 '<td colspan="' + headerCt.getColumnCount() + '">',
91386                     '<div class="' + this.nodeAnimWrapCls + '">',
91387                         '<table class="' + Ext.baseCSSPrefix + 'grid-table" style="width: ' + headerCt.getFullWidth() + 'px;"><tbody>',
91388                             thHtml,
91389                         '</tbody></table>',
91390                     '</div>',
91391                 '</td>'
91392             ].join('')
91393         }, 'after');
91394
91395         return {
91396             record: record,
91397             node: node,
91398             el: tmpEl,
91399             expanding: false,
91400             collapsing: false,
91401             animating: false,
91402             animateEl: tmpEl.down('div'),
91403             targetEl: tmpEl.down('tbody')
91404         };
91405     },
91406
91407     getAnimWrap: function(parent) {
91408         if (!this.animate) {
91409             return null;
91410         }
91411
91412         
91413         while (parent) {
91414             if (parent.animWrap) {
91415                 return parent.animWrap;
91416             }
91417             parent = parent.parentNode;
91418         }
91419         return null;
91420     },
91421
91422     doAdd: function(nodes, records, index) {
91423         
91424         
91425         var me = this,
91426             record = records[0],
91427             parent = record.parentNode,
91428             a = me.all.elements,
91429             relativeIndex = 0,
91430             animWrap = me.getAnimWrap(parent),
91431             targetEl, children, len;
91432
91433         if (!animWrap || !animWrap.expanding) {
91434             me.resetScrollers();
91435             return me.callParent(arguments);
91436         }
91437
91438         
91439         parent = animWrap.record;
91440         
91441         
91442         targetEl = animWrap.targetEl;
91443         children = targetEl.dom.childNodes;
91444         
91445         
91446         len = children.length - 1;
91447         
91448         
91449         relativeIndex = index - me.indexOf(parent) - 1;
91450         
91451         
91452         
91453         if (!len || relativeIndex >= len) {
91454             targetEl.appendChild(nodes);
91455         }
91456         
91457         
91458         else {
91459             
91460             Ext.fly(children[relativeIndex + 1]).insertSibling(nodes, 'before', true);
91461         }
91462
91463         
91464         Ext.Array.insert(a, index, nodes);
91465         
91466         
91467         
91468         if (animWrap.isAnimating) {
91469             me.onExpand(parent);
91470         }
91471     },
91472     
91473     beginBulkUpdate: function(){
91474         this.bulkUpdate = true;
91475         this.ownerCt.changingScrollbars = true;  
91476     },
91477     
91478     endBulkUpdate: function(){
91479         var me = this,
91480             ownerCt = me.ownerCt;
91481         
91482         me.bulkUpdate = false;
91483         me.ownerCt.changingScrollbars = true;  
91484         me.resetScrollers();  
91485     },
91486     
91487     onRemove : function(ds, record, index) {
91488         var me = this,
91489             bulk = me.bulkUpdate;
91490
91491         me.doRemove(record, index);
91492         if (!bulk) {
91493             me.updateIndexes(index);
91494         }
91495         if (me.store.getCount() === 0){
91496             me.refresh();
91497         }
91498         if (!bulk) {
91499             me.fireEvent('itemremove', record, index);
91500         }
91501     },
91502     
91503     doRemove: function(record, index) {
91504         
91505         
91506         var me = this,
91507             parent = record.parentNode,
91508             all = me.all,
91509             animWrap = me.getAnimWrap(record),
91510             node = all.item(index).dom;
91511
91512         if (!animWrap || !animWrap.collapsing) {
91513             me.resetScrollers();
91514             return me.callParent(arguments);
91515         }
91516
91517         animWrap.targetEl.appendChild(node);
91518         all.removeElement(index);
91519     },
91520
91521     onBeforeExpand: function(parent, records, index) {
91522         var me = this,
91523             animWrap;
91524             
91525         if (!me.rendered || !me.animate) {
91526             return;
91527         }
91528
91529         if (me.getNode(parent)) {
91530             animWrap = me.getAnimWrap(parent);
91531             if (!animWrap) {
91532                 animWrap = parent.animWrap = me.createAnimWrap(parent);
91533                 animWrap.animateEl.setHeight(0);
91534             }
91535             else if (animWrap.collapsing) {
91536                 
91537                 
91538                 animWrap.targetEl.select(me.itemSelector).remove();
91539             } 
91540             animWrap.expanding = true;
91541             animWrap.collapsing = false;
91542         }
91543     },
91544
91545     onExpand: function(parent) {
91546         var me = this,
91547             queue = me.animQueue,
91548             id = parent.getId(),
91549             animWrap,
91550             animateEl, 
91551             targetEl,
91552             queueItem;        
91553         
91554         if (me.singleExpand) {
91555             me.ensureSingleExpand(parent);
91556         }
91557         
91558         animWrap = me.getAnimWrap(parent);
91559
91560         if (!animWrap) {
91561             me.resetScrollers();
91562             return;
91563         }
91564         
91565         animateEl = animWrap.animateEl;
91566         targetEl = animWrap.targetEl;
91567
91568         animateEl.stopAnimation();
91569         
91570         queue[id] = true;
91571         animateEl.slideIn('t', {
91572             duration: me.expandDuration,
91573             listeners: {
91574                 scope: me,
91575                 lastframe: function() {
91576                     
91577                     animWrap.el.insertSibling(targetEl.query(me.itemSelector), 'before');
91578                     animWrap.el.remove();
91579                     me.resetScrollers();
91580                     delete animWrap.record.animWrap;
91581                     delete queue[id];
91582                 }
91583             }
91584         });
91585         
91586         animWrap.isAnimating = true;
91587     },
91588     
91589     resetScrollers: function(){
91590         if (!this.bulkUpdate) {
91591             var panel = this.panel;
91592             
91593             panel.determineScrollbars();
91594             panel.invalidateScroller();
91595         }
91596     },
91597
91598     onBeforeCollapse: function(parent, records, index) {
91599         var me = this,
91600             animWrap;
91601             
91602         if (!me.rendered || !me.animate) {
91603             return;
91604         }
91605
91606         if (me.getNode(parent)) {
91607             animWrap = me.getAnimWrap(parent);
91608             if (!animWrap) {
91609                 animWrap = parent.animWrap = me.createAnimWrap(parent, index);
91610             }
91611             else if (animWrap.expanding) {
91612                 
91613                 
91614                 animWrap.targetEl.select(this.itemSelector).remove();
91615             }
91616             animWrap.expanding = false;
91617             animWrap.collapsing = true;
91618         }
91619     },
91620     
91621     onCollapse: function(parent) {
91622         var me = this,
91623             queue = me.animQueue,
91624             id = parent.getId(),
91625             animWrap = me.getAnimWrap(parent),
91626             animateEl, targetEl;
91627
91628         if (!animWrap) {
91629             me.resetScrollers();
91630             return;
91631         }
91632         
91633         animateEl = animWrap.animateEl;
91634         targetEl = animWrap.targetEl;
91635
91636         queue[id] = true;
91637         
91638         
91639         animateEl.stopAnimation();
91640         animateEl.slideOut('t', {
91641             duration: me.collapseDuration,
91642             listeners: {
91643                 scope: me,
91644                 lastframe: function() {
91645                     animWrap.el.remove();
91646                     delete animWrap.record.animWrap;
91647                     me.resetScrollers();
91648                     delete queue[id];
91649                 }             
91650             }
91651         });
91652         animWrap.isAnimating = true;
91653     },
91654     
91655     
91656     isAnimating: function(node) {
91657         return !!this.animQueue[node.getId()];    
91658     },
91659     
91660     collectData: function(records) {
91661         var data = this.callParent(arguments),
91662             rows = data.rows,
91663             len = rows.length,
91664             i = 0,
91665             row, record;
91666             
91667         for (; i < len; i++) {
91668             row = rows[i];
91669             record = records[i];
91670             if (record.get('qtip')) {
91671                 row.rowAttr = 'data-qtip="' + record.get('qtip') + '"';
91672                 if (record.get('qtitle')) {
91673                     row.rowAttr += ' ' + 'data-qtitle="' + record.get('qtitle') + '"';
91674                 }
91675             }
91676             if (record.isExpanded()) {
91677                 row.rowCls = (row.rowCls || '') + ' ' + this.expandedCls;
91678             }
91679             if (record.isLoading()) {
91680                 row.rowCls = (row.rowCls || '') + ' ' + this.loadingCls;
91681             }
91682         }
91683         
91684         return data;
91685     },
91686     
91687     
91688     expand: function(record, deep, callback, scope) {
91689         return record.expand(deep, callback, scope);
91690     },
91691     
91692     
91693     collapse: function(record, deep, callback, scope) {
91694         return record.collapse(deep, callback, scope);
91695     },
91696     
91697     
91698     toggle: function(record) {
91699         this[record.isExpanded() ? 'collapse' : 'expand'](record);
91700     },
91701     
91702     onItemDblClick: function(record, item, index) {
91703         this.callParent(arguments);
91704         if (this.toggleOnDblClick) {
91705             this.toggle(record);
91706         }
91707     },
91708     
91709     onBeforeItemMouseDown: function(record, item, index, e) {
91710         if (e.getTarget(this.expanderSelector, item)) {
91711             return false;
91712         }
91713         return this.callParent(arguments);
91714     },
91715     
91716     onItemClick: function(record, item, index, e) {
91717         if (e.getTarget(this.expanderSelector, item)) {
91718             this.toggle(record);
91719             return false;
91720         }
91721         return this.callParent(arguments);
91722     },
91723     
91724     onExpanderMouseOver: function(e, t) {
91725         e.getTarget(this.cellSelector, 10, true).addCls(this.expanderIconOverCls);
91726     },
91727     
91728     onExpanderMouseOut: function(e, t) {
91729         e.getTarget(this.cellSelector, 10, true).removeCls(this.expanderIconOverCls);
91730     },
91731     
91732     
91733     getTreeStore: function() {
91734         return this.panel.store;
91735     },    
91736     
91737     ensureSingleExpand: function(node) {
91738         var parent = node.parentNode;
91739         if (parent) {
91740             parent.eachChild(function(child) {
91741                 if (child !== node && child.isExpanded()) {
91742                     child.collapse();
91743                 }
91744             });
91745         }
91746     }
91747 });
91748
91749 Ext.define('Ext.tree.Panel', {
91750     extend: 'Ext.panel.Table',
91751     alias: 'widget.treepanel',
91752     alternateClassName: ['Ext.tree.TreePanel', 'Ext.TreePanel'],
91753     requires: ['Ext.tree.View', 'Ext.selection.TreeModel', 'Ext.tree.Column'],
91754     viewType: 'treeview',
91755     selType: 'treemodel',
91756
91757     treeCls: Ext.baseCSSPrefix + 'tree-panel',
91758
91759     deferRowRender: false,
91760
91761     
91762     lines: true,
91763
91764     
91765     useArrows: false,
91766
91767     
91768     singleExpand: false,
91769
91770     ddConfig: {
91771         enableDrag: true,
91772         enableDrop: true
91773     },
91774
91775     
91776
91777     
91778     rootVisible: true,
91779
91780     
91781     displayField: 'text',
91782
91783     
91784     root: null,
91785
91786     
91787     
91788     normalCfgCopy: ['displayField', 'root', 'singleExpand', 'useArrows', 'lines', 'rootVisible', 'scroll'],
91789     lockedCfgCopy: ['displayField', 'root', 'singleExpand', 'useArrows', 'lines', 'rootVisible'],
91790
91791     
91792
91793     
91794
91795     constructor: function(config) {
91796         config = config || {};
91797         if (config.animate === undefined) {
91798             config.animate = Ext.enableFx;
91799         }
91800         this.enableAnimations = config.animate;
91801         delete config.animate;
91802
91803         this.callParent([config]);
91804     },
91805
91806     initComponent: function() {
91807         var me = this,
91808             cls = [me.treeCls];
91809
91810         if (me.useArrows) {
91811             cls.push(Ext.baseCSSPrefix + 'tree-arrows');
91812             me.lines = false;
91813         }
91814
91815         if (me.lines) {
91816             cls.push(Ext.baseCSSPrefix + 'tree-lines');
91817         } else if (!me.useArrows) {
91818             cls.push(Ext.baseCSSPrefix + 'tree-no-lines');
91819         }
91820
91821         if (Ext.isString(me.store)) {
91822             me.store = Ext.StoreMgr.lookup(me.store);
91823         } else if (!me.store || Ext.isObject(me.store) && !me.store.isStore) {
91824             me.store = Ext.create('Ext.data.TreeStore', Ext.apply({}, me.store || {}, {
91825                 root: me.root,
91826                 fields: me.fields,
91827                 model: me.model,
91828                 folderSort: me.folderSort
91829             }));
91830         } else if (me.root) {
91831             me.store = Ext.data.StoreManager.lookup(me.store);
91832             me.store.setRootNode(me.root);
91833             if (me.folderSort !== undefined) {
91834                 me.store.folderSort = me.folderSort;
91835                 me.store.sort();
91836             }
91837         }
91838
91839         
91840         
91841         
91842         
91843
91844         me.viewConfig = Ext.applyIf(me.viewConfig || {}, {
91845             rootVisible: me.rootVisible,
91846             animate: me.enableAnimations,
91847             singleExpand: me.singleExpand,
91848             node: me.store.getRootNode(),
91849             hideHeaders: me.hideHeaders
91850         });
91851
91852         me.mon(me.store, {
91853             scope: me,
91854             rootchange: me.onRootChange,
91855             clear: me.onClear
91856         });
91857
91858         me.relayEvents(me.store, [
91859             
91860             'beforeload',
91861
91862             
91863             'load'
91864         ]);
91865
91866         me.store.on({
91867             
91868             append: me.createRelayer('itemappend'),
91869
91870             
91871             remove: me.createRelayer('itemremove'),
91872
91873             
91874             move: me.createRelayer('itemmove'),
91875
91876             
91877             insert: me.createRelayer('iteminsert'),
91878
91879             
91880             beforeappend: me.createRelayer('beforeitemappend'),
91881
91882             
91883             beforeremove: me.createRelayer('beforeitemremove'),
91884
91885             
91886             beforemove: me.createRelayer('beforeitemmove'),
91887
91888             
91889             beforeinsert: me.createRelayer('beforeiteminsert'),
91890
91891             
91892             expand: me.createRelayer('itemexpand'),
91893
91894             
91895             collapse: me.createRelayer('itemcollapse'),
91896
91897             
91898             beforeexpand: me.createRelayer('beforeitemexpand'),
91899
91900             
91901             beforecollapse: me.createRelayer('beforeitemcollapse')
91902         });
91903
91904         
91905         if (!me.columns) {
91906             if (me.initialConfig.hideHeaders === undefined) {
91907                 me.hideHeaders = true;
91908             }
91909             me.columns = [{
91910                 xtype    : 'treecolumn',
91911                 text     : 'Name',
91912                 flex     : 1,
91913                 dataIndex: me.displayField
91914             }];
91915         }
91916
91917         if (me.cls) {
91918             cls.push(me.cls);
91919         }
91920         me.cls = cls.join(' ');
91921         me.callParent();
91922
91923         me.relayEvents(me.getView(), [
91924             
91925             'checkchange'
91926         ]);
91927
91928         
91929         if (!me.getView().rootVisible && !me.getRootNode()) {
91930             me.setRootNode({
91931                 expanded: true
91932             });
91933         }
91934     },
91935
91936     onClear: function(){
91937         this.view.onClear();
91938     },
91939
91940     
91941     setRootNode: function() {
91942         return this.store.setRootNode.apply(this.store, arguments);
91943     },
91944
91945     
91946     getRootNode: function() {
91947         return this.store.getRootNode();
91948     },
91949
91950     onRootChange: function(root) {
91951         this.view.setRootNode(root);
91952     },
91953
91954     
91955     getChecked: function() {
91956         return this.getView().getChecked();
91957     },
91958
91959     isItemChecked: function(rec) {
91960         return rec.get('checked');
91961     },
91962
91963     
91964     expandAll : function(callback, scope) {
91965         var root = this.getRootNode(),
91966             animate = this.enableAnimations,
91967             view = this.getView();
91968         if (root) {
91969             if (!animate) {
91970                 view.beginBulkUpdate();
91971             }
91972             root.expand(true, callback, scope);
91973             if (!animate) {
91974                 view.endBulkUpdate();
91975             }
91976         }
91977     },
91978
91979     
91980     collapseAll : function(callback, scope) {
91981         var root = this.getRootNode(),
91982             animate = this.enableAnimations,
91983             view = this.getView();
91984
91985         if (root) {
91986             if (!animate) {
91987                 view.beginBulkUpdate();
91988             }
91989             if (view.rootVisible) {
91990                 root.collapse(true, callback, scope);
91991             } else {
91992                 root.collapseChildren(true, callback, scope);
91993             }
91994             if (!animate) {
91995                 view.endBulkUpdate();
91996             }
91997         }
91998     },
91999
92000     
92001     expandPath: function(path, field, separator, callback, scope) {
92002         var me = this,
92003             current = me.getRootNode(),
92004             index = 1,
92005             view = me.getView(),
92006             keys,
92007             expander;
92008
92009         field = field || me.getRootNode().idProperty;
92010         separator = separator || '/';
92011
92012         if (Ext.isEmpty(path)) {
92013             Ext.callback(callback, scope || me, [false, null]);
92014             return;
92015         }
92016
92017         keys = path.split(separator);
92018         if (current.get(field) != keys[1]) {
92019             
92020             Ext.callback(callback, scope || me, [false, current]);
92021             return;
92022         }
92023
92024         expander = function(){
92025             if (++index === keys.length) {
92026                 Ext.callback(callback, scope || me, [true, current]);
92027                 return;
92028             }
92029             var node = current.findChild(field, keys[index]);
92030             if (!node) {
92031                 Ext.callback(callback, scope || me, [false, current]);
92032                 return;
92033             }
92034             current = node;
92035             current.expand(false, expander);
92036         };
92037         current.expand(false, expander);
92038     },
92039
92040     
92041     selectPath: function(path, field, separator, callback, scope) {
92042         var me = this,
92043             keys,
92044             last;
92045
92046         field = field || me.getRootNode().idProperty;
92047         separator = separator || '/';
92048
92049         keys = path.split(separator);
92050         last = keys.pop();
92051
92052         me.expandPath(keys.join(separator), field, separator, function(success, node){
92053             var doSuccess = false;
92054             if (success && node) {
92055                 node = node.findChild(field, last);
92056                 if (node) {
92057                     me.getSelectionModel().select(node);
92058                     Ext.callback(callback, scope || me, [true, node]);
92059                     doSuccess = true;
92060                 }
92061             } else if (node === me.getRootNode()) {
92062                 doSuccess = true;
92063             }
92064             Ext.callback(callback, scope || me, [doSuccess, node]);
92065         }, me);
92066     }
92067 });
92068
92069
92070 Ext.define('Ext.view.DragZone', {
92071     extend: 'Ext.dd.DragZone',
92072     containerScroll: false,
92073
92074     constructor: function(config) {
92075         var me = this;
92076
92077         Ext.apply(me, config);
92078
92079         
92080         
92081         
92082         
92083         
92084         if (!me.ddGroup) {
92085             me.ddGroup = 'view-dd-zone-' + me.view.id;
92086         }
92087
92088         
92089         
92090         
92091         
92092         
92093         
92094         
92095         me.callParent([me.view.el.dom.parentNode]);
92096
92097         me.ddel = Ext.get(document.createElement('div'));
92098         me.ddel.addCls(Ext.baseCSSPrefix + 'grid-dd-wrap');
92099     },
92100
92101     init: function(id, sGroup, config) {
92102         this.initTarget(id, sGroup, config);
92103         this.view.mon(this.view, {
92104             itemmousedown: this.onItemMouseDown,
92105             scope: this
92106         });
92107     },
92108
92109     onItemMouseDown: function(view, record, item, index, e) {
92110         if (!this.isPreventDrag(e, record, item, index)) {
92111             this.handleMouseDown(e);
92112
92113             
92114             
92115             if (view.getSelectionModel().selectionMode == 'MULTI' && !e.ctrlKey && view.getSelectionModel().isSelected(record)) {
92116                 return false;
92117             }
92118         }
92119     },
92120
92121     
92122     isPreventDrag: function(e) {
92123         return false;
92124     },
92125
92126     getDragData: function(e) {
92127         var view = this.view,
92128             item = e.getTarget(view.getItemSelector()),
92129             record, selectionModel, records;
92130
92131         if (item) {
92132             record = view.getRecord(item);
92133             selectionModel = view.getSelectionModel();
92134             records = selectionModel.getSelection();
92135             return {
92136                 copy: this.view.copy || (this.view.allowCopy && e.ctrlKey),
92137                 event: new Ext.EventObjectImpl(e),
92138                 view: view,
92139                 ddel: this.ddel,
92140                 item: item,
92141                 records: records,
92142                 fromPosition: Ext.fly(item).getXY()
92143             };
92144         }
92145     },
92146
92147     onInitDrag: function(x, y) {
92148         var me = this,
92149             data = me.dragData,
92150             view = data.view,
92151             selectionModel = view.getSelectionModel(),
92152             record = view.getRecord(data.item),
92153             e = data.event;
92154
92155         
92156         
92157         if (!selectionModel.isSelected(record) || e.hasModifier()) {
92158             selectionModel.selectWithEvent(record, e, true);
92159         }
92160         data.records = selectionModel.getSelection();
92161
92162         me.ddel.update(me.getDragText());
92163         me.proxy.update(me.ddel.dom);
92164         me.onStartDrag(x, y);
92165         return true;
92166     },
92167
92168     getDragText: function() {
92169         var count = this.dragData.records.length;
92170         return Ext.String.format(this.dragText, count, count == 1 ? '' : 's');
92171     },
92172
92173     getRepairXY : function(e, data){
92174         return data ? data.fromPosition : false;
92175     }
92176 });
92177 Ext.define('Ext.tree.ViewDragZone', {
92178     extend: 'Ext.view.DragZone',
92179
92180     isPreventDrag: function(e, record) {
92181         return (record.get('allowDrag') === false) || !!e.getTarget(this.view.expanderSelector);
92182     },
92183     
92184     afterRepair: function() {
92185         var me = this,
92186             view = me.view,
92187             selectedRowCls = view.selectedItemCls,
92188             records = me.dragData.records,
92189             fly = Ext.fly;
92190         
92191         if (Ext.enableFx && me.repairHighlight) {
92192             
92193             Ext.Array.forEach(records, function(record) {
92194                 
92195                 
92196                 var item = view.getNode(record);
92197                 
92198                 
92199                 
92200                 fly(item.firstChild).highlight(me.repairHighlightColor, {
92201                     listeners: {
92202                         beforeanimate: function() {
92203                             if (view.isSelected(item)) {
92204                                 fly(item).removeCls(selectedRowCls);
92205                             }
92206                         },
92207                         afteranimate: function() {
92208                             if (view.isSelected(item)) {
92209                                 fly(item).addCls(selectedRowCls);
92210                             }
92211                         }
92212                     }
92213                 });
92214             });
92215         }
92216         me.dragging = false;
92217     }
92218 });
92219
92220 Ext.define('Ext.tree.ViewDropZone', {
92221     extend: 'Ext.view.DropZone',
92222
92223     
92224     allowParentInserts: false,
92225  
92226     
92227     allowContainerDrops: false,
92228
92229     
92230     appendOnly: false,
92231
92232     
92233     expandDelay : 500,
92234
92235     indicatorCls: 'x-tree-ddindicator',
92236
92237     
92238     expandNode : function(node) {
92239         var view = this.view;
92240         if (!node.isLeaf() && !node.isExpanded()) {
92241             view.expand(node);
92242             this.expandProcId = false;
92243         }
92244     },
92245
92246     
92247     queueExpand : function(node) {
92248         this.expandProcId = Ext.Function.defer(this.expandNode, this.expandDelay, this, [node]);
92249     },
92250
92251     
92252     cancelExpand : function() {
92253         if (this.expandProcId) {
92254             clearTimeout(this.expandProcId);
92255             this.expandProcId = false;
92256         }
92257     },
92258
92259     getPosition: function(e, node) {
92260         var view = this.view,
92261             record = view.getRecord(node),
92262             y = e.getPageY(),
92263             noAppend = record.isLeaf(),
92264             noBelow = false,
92265             region = Ext.fly(node).getRegion(),
92266             fragment;
92267
92268         
92269         if (record.isRoot()) {
92270             return 'append';
92271         }
92272
92273         
92274         if (this.appendOnly) {
92275             return noAppend ? false : 'append';
92276         }
92277
92278         if (!this.allowParentInsert) {
92279             noBelow = record.hasChildNodes() && record.isExpanded();
92280         }
92281
92282         fragment = (region.bottom - region.top) / (noAppend ? 2 : 3);
92283         if (y >= region.top && y < (region.top + fragment)) {
92284             return 'before';
92285         }
92286         else if (!noBelow && (noAppend || (y >= (region.bottom - fragment) && y <= region.bottom))) {
92287             return 'after';
92288         }
92289         else {
92290             return 'append';
92291         }
92292     },
92293
92294     isValidDropPoint : function(node, position, dragZone, e, data) {
92295         if (!node || !data.item) {
92296             return false;
92297         }
92298
92299         var view = this.view,
92300             targetNode = view.getRecord(node),
92301             draggedRecords = data.records,
92302             dataLength = draggedRecords.length,
92303             ln = draggedRecords.length,
92304             i, record;
92305
92306         
92307         if (!(targetNode && position && dataLength)) {
92308             return false;
92309         }
92310
92311         
92312         for (i = 0; i < ln; i++) {
92313             record = draggedRecords[i];
92314             if (record.isNode && record.contains(targetNode)) {
92315                 return false;
92316             }
92317         }
92318         
92319         
92320         if (position === 'append' && targetNode.get('allowDrop') === false) {
92321             return false;
92322         }
92323         else if (position != 'append' && targetNode.parentNode.get('allowDrop') === false) {
92324             return false;
92325         }
92326
92327         
92328         if (Ext.Array.contains(draggedRecords, targetNode)) {
92329              return false;
92330         }
92331
92332         
92333         
92334         return true;
92335     },
92336
92337     onNodeOver : function(node, dragZone, e, data) {
92338         var position = this.getPosition(e, node),
92339             returnCls = this.dropNotAllowed,
92340             view = this.view,
92341             targetNode = view.getRecord(node),
92342             indicator = this.getIndicator(),
92343             indicatorX = 0,
92344             indicatorY = 0;
92345
92346         
92347         this.cancelExpand();
92348         if (position == 'append' && !this.expandProcId && !Ext.Array.contains(data.records, targetNode) && !targetNode.isLeaf() && !targetNode.isExpanded()) {
92349             this.queueExpand(targetNode);
92350         }
92351             
92352             
92353         if (this.isValidDropPoint(node, position, dragZone, e, data)) {
92354             this.valid = true;
92355             this.currentPosition = position;
92356             this.overRecord = targetNode;
92357
92358             indicator.setWidth(Ext.fly(node).getWidth());
92359             indicatorY = Ext.fly(node).getY() - Ext.fly(view.el).getY() - 1;
92360
92361             
92362             if (position == 'before') {
92363                 returnCls = targetNode.isFirst() ? Ext.baseCSSPrefix + 'tree-drop-ok-above' : Ext.baseCSSPrefix + 'tree-drop-ok-between';
92364                 indicator.showAt(0, indicatorY);
92365                 dragZone.proxy.show();
92366             } else if (position == 'after') {
92367                 returnCls = targetNode.isLast() ? Ext.baseCSSPrefix + 'tree-drop-ok-below' : Ext.baseCSSPrefix + 'tree-drop-ok-between';
92368                 indicatorY += Ext.fly(node).getHeight();
92369                 indicator.showAt(0, indicatorY);
92370                 dragZone.proxy.show();
92371             } else {
92372                 returnCls = Ext.baseCSSPrefix + 'tree-drop-ok-append';
92373                 
92374                 indicator.hide();
92375             }
92376         } else {
92377             this.valid = false;
92378         }
92379
92380         this.currentCls = returnCls;
92381         return returnCls;
92382     },
92383
92384     onContainerOver : function(dd, e, data) {
92385         return e.getTarget('.' + this.indicatorCls) ? this.currentCls : this.dropNotAllowed;
92386     },
92387     
92388     notifyOut: function() {
92389         this.callParent(arguments);
92390         this.cancelExpand();
92391     },
92392
92393     handleNodeDrop : function(data, targetNode, position) {
92394         var me = this,
92395             view = me.view,
92396             parentNode = targetNode.parentNode,
92397             store = view.getStore(),
92398             recordDomNodes = [],
92399             records, i, len,
92400             insertionMethod, argList,
92401             needTargetExpand,
92402             transferData,
92403             processDrop;
92404
92405         
92406         if (data.copy) {
92407             records = data.records;
92408             data.records = [];
92409             for (i = 0, len = records.length; i < len; i++) {
92410                 data.records.push(Ext.apply({}, records[i].data));
92411             }
92412         }
92413
92414         
92415         me.cancelExpand();
92416
92417         
92418         
92419         
92420         
92421         if (position == 'before') {
92422             insertionMethod = parentNode.insertBefore;
92423             argList = [null, targetNode];
92424             targetNode = parentNode;
92425         }
92426         else if (position == 'after') {
92427             if (targetNode.nextSibling) {
92428                 insertionMethod = parentNode.insertBefore;
92429                 argList = [null, targetNode.nextSibling];
92430             }
92431             else {
92432                 insertionMethod = parentNode.appendChild;
92433                 argList = [null];
92434             }
92435             targetNode = parentNode;
92436         }
92437         else {
92438             if (!targetNode.isExpanded()) {
92439                 needTargetExpand = true;
92440             }
92441             insertionMethod = targetNode.appendChild;
92442             argList = [null];
92443         }
92444
92445         
92446         transferData = function() {
92447             var node;
92448             for (i = 0, len = data.records.length; i < len; i++) {
92449                 argList[0] = data.records[i];
92450                 node = insertionMethod.apply(targetNode, argList);
92451                 
92452                 if (Ext.enableFx && me.dropHighlight) {
92453                     recordDomNodes.push(view.getNode(node));
92454                 }
92455             }
92456             
92457             
92458             
92459             if (Ext.enableFx && me.dropHighlight) {
92460                 
92461                 
92462                 Ext.Array.forEach(recordDomNodes, function(n) {
92463                     if (n) {
92464                         Ext.fly(n.firstChild ? n.firstChild : n).highlight(me.dropHighlightColor);
92465                     }
92466                 });
92467             }
92468         };
92469
92470         
92471         if (needTargetExpand) {
92472             targetNode.expand(false, transferData);
92473         }
92474         
92475         else {
92476             transferData();
92477         }
92478     }
92479 });
92480
92481 Ext.define('Ext.tree.plugin.TreeViewDragDrop', {
92482     extend: 'Ext.AbstractPlugin',
92483     alias: 'plugin.treeviewdragdrop',
92484
92485     uses: [
92486         'Ext.tree.ViewDragZone',
92487         'Ext.tree.ViewDropZone'
92488     ],
92489
92490     
92491
92492     
92493
92494     dragText : '{0} selected node{1}',
92495
92496     
92497     allowParentInserts: false,
92498
92499     
92500     allowContainerDrops: false,
92501
92502     
92503     appendOnly: false,
92504
92505     
92506     ddGroup : "TreeDD",
92507
92508     
92509
92510     
92511
92512     
92513     expandDelay : 1000,
92514
92515     
92516     enableDrop: true,
92517
92518     
92519     enableDrag: true,
92520
92521     
92522     nodeHighlightColor: 'c3daf9',
92523
92524     
92525     nodeHighlightOnDrop: Ext.enableFx,
92526
92527     
92528     nodeHighlightOnRepair: Ext.enableFx,
92529
92530     init : function(view) {
92531         view.on('render', this.onViewRender, this, {single: true});
92532     },
92533
92534     
92535     destroy: function() {
92536         Ext.destroy(this.dragZone, this.dropZone);
92537     },
92538
92539     onViewRender : function(view) {
92540         var me = this;
92541
92542         if (me.enableDrag) {
92543             me.dragZone = Ext.create('Ext.tree.ViewDragZone', {
92544                 view: view,
92545                 ddGroup: me.dragGroup || me.ddGroup,
92546                 dragText: me.dragText,
92547                 repairHighlightColor: me.nodeHighlightColor,
92548                 repairHighlight: me.nodeHighlightOnRepair
92549             });
92550         }
92551
92552         if (me.enableDrop) {
92553             me.dropZone = Ext.create('Ext.tree.ViewDropZone', {
92554                 view: view,
92555                 ddGroup: me.dropGroup || me.ddGroup,
92556                 allowContainerDrops: me.allowContainerDrops,
92557                 appendOnly: me.appendOnly,
92558                 allowParentInserts: me.allowParentInserts,
92559                 expandDelay: me.expandDelay,
92560                 dropHighlightColor: me.nodeHighlightColor,
92561                 dropHighlight: me.nodeHighlightOnDrop
92562             });
92563         }
92564     }
92565 });
92566
92567 Ext.define('Ext.util.Cookies', {
92568     singleton: true,
92569     
92570     
92571     set : function(name, value){
92572         var argv = arguments,
92573             argc = arguments.length,
92574             expires = (argc > 2) ? argv[2] : null,
92575             path = (argc > 3) ? argv[3] : '/',
92576             domain = (argc > 4) ? argv[4] : null,
92577             secure = (argc > 5) ? argv[5] : false;
92578             
92579         document.cookie = name + "=" + escape(value) + ((expires === null) ? "" : ("; expires=" + expires.toGMTString())) + ((path === null) ? "" : ("; path=" + path)) + ((domain === null) ? "" : ("; domain=" + domain)) + ((secure === true) ? "; secure" : "");
92580     },
92581
92582     
92583     get : function(name){
92584         var arg = name + "=",
92585             alen = arg.length,
92586             clen = document.cookie.length,
92587             i = 0,
92588             j = 0;
92589             
92590         while(i < clen){
92591             j = i + alen;
92592             if(document.cookie.substring(i, j) == arg){
92593                 return this.getCookieVal(j);
92594             }
92595             i = document.cookie.indexOf(" ", i) + 1;
92596             if(i === 0){
92597                 break;
92598             }
92599         }
92600         return null;
92601     },
92602
92603     
92604     clear : function(name, path){
92605         if(this.get(name)){
92606             path = path || '/';
92607             document.cookie = name + '=' + '; expires=Thu, 01-Jan-70 00:00:01 GMT; path=' + path;
92608         }
92609     },
92610     
92611     
92612     getCookieVal : function(offset){
92613         var endstr = document.cookie.indexOf(";", offset);
92614         if(endstr == -1){
92615             endstr = document.cookie.length;
92616         }
92617         return unescape(document.cookie.substring(offset, endstr));
92618     }
92619 });
92620
92621
92622 Ext.define('Ext.util.CSS', function() {
92623     var rules = null;
92624     var doc = document;
92625
92626     var camelRe = /(-[a-z])/gi;
92627     var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
92628
92629     return {
92630
92631         singleton: true,
92632
92633         constructor: function() {
92634             this.rules = {};
92635             this.initialized = false;
92636         },
92637
92638         
92639         createStyleSheet : function(cssText, id) {
92640             var ss,
92641                 head = doc.getElementsByTagName("head")[0],
92642                 styleEl = doc.createElement("style");
92643
92644             styleEl.setAttribute("type", "text/css");
92645             if (id) {
92646                styleEl.setAttribute("id", id);
92647             }
92648
92649             if (Ext.isIE) {
92650                head.appendChild(styleEl);
92651                ss = styleEl.styleSheet;
92652                ss.cssText = cssText;
92653             } else {
92654                 try{
92655                     styleEl.appendChild(doc.createTextNode(cssText));
92656                 } catch(e) {
92657                    styleEl.cssText = cssText;
92658                 }
92659                 head.appendChild(styleEl);
92660                 ss = styleEl.styleSheet ? styleEl.styleSheet : (styleEl.sheet || doc.styleSheets[doc.styleSheets.length-1]);
92661             }
92662             this.cacheStyleSheet(ss);
92663             return ss;
92664         },
92665
92666         
92667         removeStyleSheet : function(id) {
92668             var existing = document.getElementById(id);
92669             if (existing) {
92670                 existing.parentNode.removeChild(existing);
92671             }
92672         },
92673
92674         
92675         swapStyleSheet : function(id, url) {
92676             var doc = document;
92677             this.removeStyleSheet(id);
92678             var ss = doc.createElement("link");
92679             ss.setAttribute("rel", "stylesheet");
92680             ss.setAttribute("type", "text/css");
92681             ss.setAttribute("id", id);
92682             ss.setAttribute("href", url);
92683             doc.getElementsByTagName("head")[0].appendChild(ss);
92684         },
92685
92686         
92687         refreshCache : function() {
92688             return this.getRules(true);
92689         },
92690
92691         
92692         cacheStyleSheet : function(ss) {
92693             if(!rules){
92694                 rules = {};
92695             }
92696             try {
92697                 var ssRules = ss.cssRules || ss.rules,
92698                     selectorText,
92699                     i = ssRules.length - 1,
92700                     j,
92701                     selectors;
92702
92703                 for (; i >= 0; --i) {
92704                     selectorText = ssRules[i].selectorText;
92705                     if (selectorText) {
92706
92707                         
92708                         selectorText = selectorText.split(',');
92709                         selectors = selectorText.length;
92710                         for (j = 0; j < selectors; j++) {
92711                             rules[Ext.String.trim(selectorText[j]).toLowerCase()] = ssRules[i];
92712                         }
92713                     }
92714                 }
92715             } catch(e) {}
92716         },
92717
92718         
92719         getRules : function(refreshCache) {
92720             if (rules === null || refreshCache) {
92721                 rules = {};
92722                 var ds = doc.styleSheets,
92723                     i = 0,
92724                     len = ds.length;
92725
92726                 for (; i < len; i++) {
92727                     try {
92728                         if (!ds[i].disabled) {
92729                             this.cacheStyleSheet(ds[i]);
92730                         }
92731                     } catch(e) {}
92732                 }
92733             }
92734             return rules;
92735         },
92736
92737         
92738         getRule: function(selector, refreshCache) {
92739             var rs = this.getRules(refreshCache);
92740             if (!Ext.isArray(selector)) {
92741                 return rs[selector.toLowerCase()];
92742             }
92743             for (var i = 0; i < selector.length; i++) {
92744                 if (rs[selector[i]]) {
92745                     return rs[selector[i].toLowerCase()];
92746                 }
92747             }
92748             return null;
92749         },
92750
92751         
92752         updateRule : function(selector, property, value){
92753             if (!Ext.isArray(selector)) {
92754                 var rule = this.getRule(selector);
92755                 if (rule) {
92756                     rule.style[property.replace(camelRe, camelFn)] = value;
92757                     return true;
92758                 }
92759             } else {
92760                 for (var i = 0; i < selector.length; i++) {
92761                     if (this.updateRule(selector[i], property, value)) {
92762                         return true;
92763                     }
92764                 }
92765             }
92766             return false;
92767         }
92768     };
92769 }());
92770
92771 Ext.define('Ext.util.History', {
92772     singleton: true,
92773     alternateClassName: 'Ext.History',
92774     mixins: {
92775         observable: 'Ext.util.Observable'
92776     },
92777
92778     constructor: function() {
92779         var me = this;
92780         me.oldIEMode = Ext.isIE6 || Ext.isIE7 || !Ext.isStrict && Ext.isIE8;
92781         me.iframe = null;
92782         me.hiddenField = null;
92783         me.ready = false;
92784         me.currentToken = null;
92785     },
92786
92787     getHash: function() {
92788         var href = window.location.href,
92789             i = href.indexOf("#");
92790
92791         return i >= 0 ? href.substr(i + 1) : null;
92792     },
92793
92794     doSave: function() {
92795         this.hiddenField.value = this.currentToken;
92796     },
92797
92798
92799     handleStateChange: function(token) {
92800         this.currentToken = token;
92801         this.fireEvent('change', token);
92802     },
92803
92804     updateIFrame: function(token) {
92805         var html = '<html><body><div id="state">' +
92806                     Ext.util.Format.htmlEncode(token) +
92807                     '</div></body></html>';
92808
92809         try {
92810             var doc = this.iframe.contentWindow.document;
92811             doc.open();
92812             doc.write(html);
92813             doc.close();
92814             return true;
92815         } catch (e) {
92816             return false;
92817         }
92818     },
92819
92820     checkIFrame: function () {
92821         var me = this,
92822             contentWindow = me.iframe.contentWindow;
92823
92824         if (!contentWindow || !contentWindow.document) {
92825             Ext.Function.defer(this.checkIFrame, 10, this);
92826             return;
92827         }
92828
92829         var doc = contentWindow.document,
92830             elem = doc.getElementById("state"),
92831             oldToken = elem ? elem.innerText : null,
92832             oldHash = me.getHash();
92833
92834         Ext.TaskManager.start({
92835             run: function () {
92836                 var doc = contentWindow.document,
92837                     elem = doc.getElementById("state"),
92838                     newToken = elem ? elem.innerText : null,
92839                     newHash = me.getHash();
92840
92841                 if (newToken !== oldToken) {
92842                     oldToken = newToken;
92843                     me.handleStateChange(newToken);
92844                     window.top.location.hash = newToken;
92845                     oldHash = newToken;
92846                     me.doSave();
92847                 } else if (newHash !== oldHash) {
92848                     oldHash = newHash;
92849                     me.updateIFrame(newHash);
92850                 }
92851             },
92852             interval: 50,
92853             scope: me
92854         });
92855         me.ready = true;
92856         me.fireEvent('ready', me);
92857     },
92858
92859     startUp: function () {
92860         var me = this;
92861
92862         me.currentToken = me.hiddenField.value || this.getHash();
92863
92864         if (me.oldIEMode) {
92865             me.checkIFrame();
92866         } else {
92867             var hash = me.getHash();
92868             Ext.TaskManager.start({
92869                 run: function () {
92870                     var newHash = me.getHash();
92871                     if (newHash !== hash) {
92872                         hash = newHash;
92873                         me.handleStateChange(hash);
92874                         me.doSave();
92875                     }
92876                 },
92877                 interval: 50,
92878                 scope: me
92879             });
92880             me.ready = true;
92881             me.fireEvent('ready', me);
92882         }
92883
92884     },
92885
92886     
92887     fieldId: Ext.baseCSSPrefix + 'history-field',
92888     
92889     iframeId: Ext.baseCSSPrefix + 'history-frame',
92890
92891     
92892     init: function (onReady, scope) {
92893         var me = this;
92894
92895         if (me.ready) {
92896             Ext.callback(onReady, scope, [me]);
92897             return;
92898         }
92899
92900         if (!Ext.isReady) {
92901             Ext.onReady(function() {
92902                 me.init(onReady, scope);
92903             });
92904             return;
92905         }
92906
92907         me.hiddenField = Ext.getDom(me.fieldId);
92908
92909         if (me.oldIEMode) {
92910             me.iframe = Ext.getDom(me.iframeId);
92911         }
92912
92913         me.addEvents(
92914             
92915             'ready',
92916             
92917             'change'
92918         );
92919
92920         if (onReady) {
92921             me.on('ready', onReady, scope, {single: true});
92922         }
92923         me.startUp();
92924     },
92925
92926     
92927     add: function (token, preventDup) {
92928         var me = this;
92929
92930         if (preventDup !== false) {
92931             if (me.getToken() === token) {
92932                 return true;
92933             }
92934         }
92935
92936         if (me.oldIEMode) {
92937             return me.updateIFrame(token);
92938         } else {
92939             window.top.location.hash = token;
92940             return true;
92941         }
92942     },
92943
92944     
92945     back: function() {
92946         window.history.go(-1);
92947     },
92948
92949     
92950     forward: function(){
92951         window.history.go(1);
92952     },
92953
92954     
92955     getToken: function() {
92956         return this.ready ? this.currentToken : this.getHash();
92957     }
92958 });
92959
92960 Ext.define('Ext.view.TableChunker', {
92961     singleton: true,
92962     requires: ['Ext.XTemplate'],
92963     metaTableTpl: [
92964         '{[this.openTableWrap()]}',
92965         '<table class="' + Ext.baseCSSPrefix + 'grid-table ' + Ext.baseCSSPrefix + 'grid-table-resizer" border="0" cellspacing="0" cellpadding="0" {[this.embedFullWidth()]}>',
92966             '<tbody>',
92967             '<tr class="' + Ext.baseCSSPrefix + 'grid-header-row">',
92968             '<tpl for="columns">',
92969                 '<th class="' + Ext.baseCSSPrefix + 'grid-col-resizer-{id}" style="width: {width}px; height: 0px;"></th>',
92970             '</tpl>',
92971             '</tr>',
92972             '{[this.openRows()]}',
92973                 '{row}',
92974                 '<tpl for="features">',
92975                     '{[this.embedFeature(values, parent, xindex, xcount)]}',
92976                 '</tpl>',
92977             '{[this.closeRows()]}',
92978             '</tbody>',
92979         '</table>',
92980         '{[this.closeTableWrap()]}'
92981     ],
92982
92983     constructor: function() {
92984         Ext.XTemplate.prototype.recurse = function(values, reference) {
92985             return this.apply(reference ? values[reference] : values);
92986         };
92987     },
92988
92989     embedFeature: function(values, parent, x, xcount) {
92990         var tpl = '';
92991         if (!values.disabled) {
92992             tpl = values.getFeatureTpl(values, parent, x, xcount);
92993         }
92994         return tpl;
92995     },
92996
92997     embedFullWidth: function() {
92998         return 'style="width: {fullWidth}px;"';
92999     },
93000
93001     openRows: function() {
93002         return '<tpl for="rows">';
93003     },
93004
93005     closeRows: function() {
93006         return '</tpl>';
93007     },
93008
93009     metaRowTpl: [
93010         '<tr class="' + Ext.baseCSSPrefix + 'grid-row {addlSelector} {[this.embedRowCls()]}" {[this.embedRowAttr()]}>',
93011             '<tpl for="columns">',
93012                 '<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>',
93013             '</tpl>',
93014         '</tr>'
93015     ],
93016     
93017     firstOrLastCls: function(xindex, xcount) {
93018         var cssCls = '';
93019         if (xindex === 1) {
93020             cssCls = Ext.baseCSSPrefix + 'grid-cell-first';
93021         } else if (xindex === xcount) {
93022             cssCls = Ext.baseCSSPrefix + 'grid-cell-last';
93023         }
93024         return cssCls;
93025     },
93026     
93027     embedRowCls: function() {
93028         return '{rowCls}';
93029     },
93030     
93031     embedRowAttr: function() {
93032         return '{rowAttr}';
93033     },
93034     
93035     openTableWrap: function() {
93036         return '';
93037     },
93038     
93039     closeTableWrap: function() {
93040         return '';
93041     },
93042
93043     getTableTpl: function(cfg, textOnly) {
93044         var tpl,
93045             tableTplMemberFns = {
93046                 openRows: this.openRows,
93047                 closeRows: this.closeRows,
93048                 embedFeature: this.embedFeature,
93049                 embedFullWidth: this.embedFullWidth,
93050                 openTableWrap: this.openTableWrap,
93051                 closeTableWrap: this.closeTableWrap
93052             },
93053             tplMemberFns = {},
93054             features = cfg.features || [],
93055             ln = features.length,
93056             i  = 0,
93057             memberFns = {
93058                 embedRowCls: this.embedRowCls,
93059                 embedRowAttr: this.embedRowAttr,
93060                 firstOrLastCls: this.firstOrLastCls
93061             },
93062             
93063             metaRowTpl = Array.prototype.slice.call(this.metaRowTpl, 0),
93064             metaTableTpl;
93065             
93066         for (; i < ln; i++) {
93067             if (!features[i].disabled) {
93068                 features[i].mutateMetaRowTpl(metaRowTpl);
93069                 Ext.apply(memberFns, features[i].getMetaRowTplFragments());
93070                 Ext.apply(tplMemberFns, features[i].getFragmentTpl());
93071                 Ext.apply(tableTplMemberFns, features[i].getTableFragments());
93072             }
93073         }
93074         
93075         metaRowTpl = Ext.create('Ext.XTemplate', metaRowTpl.join(''), memberFns);
93076         cfg.row = metaRowTpl.applyTemplate(cfg);
93077         
93078         metaTableTpl = Ext.create('Ext.XTemplate', this.metaTableTpl.join(''), tableTplMemberFns);
93079         
93080         tpl = metaTableTpl.applyTemplate(cfg);
93081         
93082         
93083         if (!textOnly) {
93084             tpl = Ext.create('Ext.XTemplate', tpl, tplMemberFns);
93085         }
93086         return tpl;
93087         
93088     }
93089 });
93090
93091
93092
93093