Upgrade to ExtJS 3.3.1 - Released 11/30/2010
[extjs.git] / ext-all-debug.js
1
2 (function(){
3
4 var EXTUTIL = Ext.util,
5     EACH = Ext.each,
6     TRUE = true,
7     FALSE = false;
8
9 EXTUTIL.Observable = function(){
10     
11     var me = this, e = me.events;
12     if(me.listeners){
13         me.on(me.listeners);
14         delete me.listeners;
15     }
16     me.events = e || {};
17 };
18
19 EXTUTIL.Observable.prototype = {
20     
21     filterOptRe : /^(?:scope|delay|buffer|single)$/,
22
23     
24     fireEvent : function(){
25         var a = Array.prototype.slice.call(arguments, 0),
26             ename = a[0].toLowerCase(),
27             me = this,
28             ret = TRUE,
29             ce = me.events[ename],
30             cc,
31             q,
32             c;
33         if (me.eventsSuspended === TRUE) {
34             if (q = me.eventQueue) {
35                 q.push(a);
36             }
37         }
38         else if(typeof ce == 'object') {
39             if (ce.bubble){
40                 if(ce.fire.apply(ce, a.slice(1)) === FALSE) {
41                     return FALSE;
42                 }
43                 c = me.getBubbleTarget && me.getBubbleTarget();
44                 if(c && c.enableBubble) {
45                     cc = c.events[ename];
46                     if(!cc || typeof cc != 'object' || !cc.bubble) {
47                         c.enableBubble(ename);
48                     }
49                     return c.fireEvent.apply(c, a);
50                 }
51             }
52             else {
53                 a.shift();
54                 ret = ce.fire.apply(ce, a);
55             }
56         }
57         return ret;
58     },
59
60     
61     addListener : function(eventName, fn, scope, o){
62         var me = this,
63             e,
64             oe,
65             ce;
66             
67         if (typeof eventName == 'object') {
68             o = eventName;
69             for (e in o) {
70                 oe = o[e];
71                 if (!me.filterOptRe.test(e)) {
72                     me.addListener(e, oe.fn || oe, oe.scope || o.scope, oe.fn ? oe : o);
73                 }
74             }
75         } else {
76             eventName = eventName.toLowerCase();
77             ce = me.events[eventName] || TRUE;
78             if (typeof ce == 'boolean') {
79                 me.events[eventName] = ce = new EXTUTIL.Event(me, eventName);
80             }
81             ce.addListener(fn, scope, typeof o == 'object' ? o : {});
82         }
83     },
84
85     
86     removeListener : function(eventName, fn, scope){
87         var ce = this.events[eventName.toLowerCase()];
88         if (typeof ce == 'object') {
89             ce.removeListener(fn, scope);
90         }
91     },
92
93     
94     purgeListeners : function(){
95         var events = this.events,
96             evt,
97             key;
98         for(key in events){
99             evt = events[key];
100             if(typeof evt == 'object'){
101                 evt.clearListeners();
102             }
103         }
104     },
105
106     
107     addEvents : function(o){
108         var me = this;
109         me.events = me.events || {};
110         if (typeof o == 'string') {
111             var a = arguments,
112                 i = a.length;
113             while(i--) {
114                 me.events[a[i]] = me.events[a[i]] || TRUE;
115             }
116         } else {
117             Ext.applyIf(me.events, o);
118         }
119     },
120
121     
122     hasListener : function(eventName){
123         var e = this.events[eventName.toLowerCase()];
124         return typeof e == 'object' && e.listeners.length > 0;
125     },
126
127     
128     suspendEvents : function(queueSuspended){
129         this.eventsSuspended = TRUE;
130         if(queueSuspended && !this.eventQueue){
131             this.eventQueue = [];
132         }
133     },
134
135     
136     resumeEvents : function(){
137         var me = this,
138             queued = me.eventQueue || [];
139         me.eventsSuspended = FALSE;
140         delete me.eventQueue;
141         EACH(queued, function(e) {
142             me.fireEvent.apply(me, e);
143         });
144     }
145 };
146
147 var OBSERVABLE = EXTUTIL.Observable.prototype;
148
149 OBSERVABLE.on = OBSERVABLE.addListener;
150
151 OBSERVABLE.un = OBSERVABLE.removeListener;
152
153
154 EXTUTIL.Observable.releaseCapture = function(o){
155     o.fireEvent = OBSERVABLE.fireEvent;
156 };
157
158 function createTargeted(h, o, scope){
159     return function(){
160         if(o.target == arguments[0]){
161             h.apply(scope, Array.prototype.slice.call(arguments, 0));
162         }
163     };
164 };
165
166 function createBuffered(h, o, l, scope){
167     l.task = new EXTUTIL.DelayedTask();
168     return function(){
169         l.task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
170     };
171 };
172
173 function createSingle(h, e, fn, scope){
174     return function(){
175         e.removeListener(fn, scope);
176         return h.apply(scope, arguments);
177     };
178 };
179
180 function createDelayed(h, o, l, scope){
181     return function(){
182         var task = new EXTUTIL.DelayedTask(),
183             args = Array.prototype.slice.call(arguments, 0);
184         if(!l.tasks) {
185             l.tasks = [];
186         }
187         l.tasks.push(task);
188         task.delay(o.delay || 10, function(){
189             l.tasks.remove(task);
190             h.apply(scope, args);
191         }, scope);
192     };
193 };
194
195 EXTUTIL.Event = function(obj, name){
196     this.name = name;
197     this.obj = obj;
198     this.listeners = [];
199 };
200
201 EXTUTIL.Event.prototype = {
202     addListener : function(fn, scope, options){
203         var me = this,
204             l;
205         scope = scope || me.obj;
206         if(!me.isListening(fn, scope)){
207             l = me.createListener(fn, scope, options);
208             if(me.firing){ 
209                 me.listeners = me.listeners.slice(0);
210             }
211             me.listeners.push(l);
212         }
213     },
214
215     createListener: function(fn, scope, o){
216         o = o || {};
217         scope = scope || this.obj;
218         var l = {
219             fn: fn,
220             scope: scope,
221             options: o
222         }, h = fn;
223         if(o.target){
224             h = createTargeted(h, o, scope);
225         }
226         if(o.delay){
227             h = createDelayed(h, o, l, scope);
228         }
229         if(o.single){
230             h = createSingle(h, this, fn, scope);
231         }
232         if(o.buffer){
233             h = createBuffered(h, o, l, scope);
234         }
235         l.fireFn = h;
236         return l;
237     },
238
239     findListener : function(fn, scope){
240         var list = this.listeners,
241             i = list.length,
242             l;
243
244         scope = scope || this.obj;
245         while(i--){
246             l = list[i];
247             if(l){
248                 if(l.fn == fn && l.scope == scope){
249                     return i;
250                 }
251             }
252         }
253         return -1;
254     },
255
256     isListening : function(fn, scope){
257         return this.findListener(fn, scope) != -1;
258     },
259
260     removeListener : function(fn, scope){
261         var index,
262             l,
263             k,
264             me = this,
265             ret = FALSE;
266         if((index = me.findListener(fn, scope)) != -1){
267             if (me.firing) {
268                 me.listeners = me.listeners.slice(0);
269             }
270             l = me.listeners[index];
271             if(l.task) {
272                 l.task.cancel();
273                 delete l.task;
274             }
275             k = l.tasks && l.tasks.length;
276             if(k) {
277                 while(k--) {
278                     l.tasks[k].cancel();
279                 }
280                 delete l.tasks;
281             }
282             me.listeners.splice(index, 1);
283             ret = TRUE;
284         }
285         return ret;
286     },
287
288     
289     clearListeners : function(){
290         var me = this,
291             l = me.listeners,
292             i = l.length;
293         while(i--) {
294             me.removeListener(l[i].fn, l[i].scope);
295         }
296     },
297
298     fire : function(){
299         var me = this,
300             listeners = me.listeners,
301             len = listeners.length,
302             i = 0,
303             l;
304
305         if(len > 0){
306             me.firing = TRUE;
307             var args = Array.prototype.slice.call(arguments, 0);
308             for (; i < len; i++) {
309                 l = listeners[i];
310                 if(l && l.fireFn.apply(l.scope || me.obj || window, args) === FALSE) {
311                     return (me.firing = FALSE);
312                 }
313             }
314         }
315         me.firing = FALSE;
316         return TRUE;
317     }
318
319 };
320 })();
321
322 Ext.DomHelper = function(){
323     var tempTableEl = null,
324         emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i,
325         tableRe = /^table|tbody|tr|td$/i,
326         confRe = /tag|children|cn|html$/i,
327         tableElRe = /td|tr|tbody/i,
328         cssRe = /([a-z0-9-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*);?/gi,
329         endRe = /end/i,
330         pub,
331         
332         afterbegin = 'afterbegin',
333         afterend = 'afterend',
334         beforebegin = 'beforebegin',
335         beforeend = 'beforeend',
336         ts = '<table>',
337         te = '</table>',
338         tbs = ts+'<tbody>',
339         tbe = '</tbody>'+te,
340         trs = tbs + '<tr>',
341         tre = '</tr>'+tbe;
342
343     
344     function doInsert(el, o, returnElement, pos, sibling, append){
345         var newNode = pub.insertHtml(pos, Ext.getDom(el), createHtml(o));
346         return returnElement ? Ext.get(newNode, true) : newNode;
347     }
348
349     
350     function createHtml(o){
351         var b = '',
352             attr,
353             val,
354             key,
355             cn;
356
357         if(typeof o == "string"){
358             b = o;
359         } else if (Ext.isArray(o)) {
360             for (var i=0; i < o.length; i++) {
361                 if(o[i]) {
362                     b += createHtml(o[i]);
363                 }
364             };
365         } else {
366             b += '<' + (o.tag = o.tag || 'div');
367             for (attr in o) {
368                 val = o[attr];
369                 if(!confRe.test(attr)){
370                     if (typeof val == "object") {
371                         b += ' ' + attr + '="';
372                         for (key in val) {
373                             b += key + ':' + val[key] + ';';
374                         };
375                         b += '"';
376                     }else{
377                         b += ' ' + ({cls : 'class', htmlFor : 'for'}[attr] || attr) + '="' + val + '"';
378                     }
379                 }
380             };
381             
382             if (emptyTags.test(o.tag)) {
383                 b += '/>';
384             } else {
385                 b += '>';
386                 if ((cn = o.children || o.cn)) {
387                     b += createHtml(cn);
388                 } else if(o.html){
389                     b += o.html;
390                 }
391                 b += '</' + o.tag + '>';
392             }
393         }
394         return b;
395     }
396
397     function ieTable(depth, s, h, e){
398         tempTableEl.innerHTML = [s, h, e].join('');
399         var i = -1,
400             el = tempTableEl,
401             ns;
402         while(++i < depth){
403             el = el.firstChild;
404         }
405
406         if(ns = el.nextSibling){
407             var df = document.createDocumentFragment();
408             while(el){
409                 ns = el.nextSibling;
410                 df.appendChild(el);
411                 el = ns;
412             }
413             el = df;
414         }
415         return el;
416     }
417
418     
419     function insertIntoTable(tag, where, el, html) {
420         var node,
421             before;
422
423         tempTableEl = tempTableEl || document.createElement('div');
424
425         if(tag == 'td' && (where == afterbegin || where == beforeend) ||
426            !tableElRe.test(tag) && (where == beforebegin || where == afterend)) {
427             return;
428         }
429         before = where == beforebegin ? el :
430                  where == afterend ? el.nextSibling :
431                  where == afterbegin ? el.firstChild : null;
432
433         if (where == beforebegin || where == afterend) {
434             el = el.parentNode;
435         }
436
437         if (tag == 'td' || (tag == 'tr' && (where == beforeend || where == afterbegin))) {
438             node = ieTable(4, trs, html, tre);
439         } else if ((tag == 'tbody' && (where == beforeend || where == afterbegin)) ||
440                    (tag == 'tr' && (where == beforebegin || where == afterend))) {
441             node = ieTable(3, tbs, html, tbe);
442         } else {
443             node = ieTable(2, ts, html, te);
444         }
445         el.insertBefore(node, before);
446         return node;
447     }
448
449
450     pub = {
451         
452         markup : function(o){
453             return createHtml(o);
454         },
455
456         
457         applyStyles : function(el, styles){
458             if (styles) {
459                 var matches;
460
461                 el = Ext.fly(el);
462                 if (typeof styles == "function") {
463                     styles = styles.call();
464                 }
465                 if (typeof styles == "string") {
466                     
467                     cssRe.lastIndex = 0;
468                     while ((matches = cssRe.exec(styles))) {
469                         el.setStyle(matches[1], matches[2]);
470                     }
471                 } else if (typeof styles == "object") {
472                     el.setStyle(styles);
473                 }
474             }
475         },
476
477         
478         insertHtml : function(where, el, html){
479             var hash = {},
480                 hashVal,
481                 setStart,
482                 range,
483                 frag,
484                 rangeEl,
485                 rs;
486
487             where = where.toLowerCase();
488             
489             hash[beforebegin] = ['BeforeBegin', 'previousSibling'];
490             hash[afterend] = ['AfterEnd', 'nextSibling'];
491
492             if (el.insertAdjacentHTML) {
493                 if(tableRe.test(el.tagName) && (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))){
494                     return rs;
495                 }
496                 
497                 hash[afterbegin] = ['AfterBegin', 'firstChild'];
498                 hash[beforeend] = ['BeforeEnd', 'lastChild'];
499                 if ((hashVal = hash[where])) {
500                     el.insertAdjacentHTML(hashVal[0], html);
501                     return el[hashVal[1]];
502                 }
503             } else {
504                 range = el.ownerDocument.createRange();
505                 setStart = 'setStart' + (endRe.test(where) ? 'After' : 'Before');
506                 if (hash[where]) {
507                     range[setStart](el);
508                     frag = range.createContextualFragment(html);
509                     el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);
510                     return el[(where == beforebegin ? 'previous' : 'next') + 'Sibling'];
511                 } else {
512                     rangeEl = (where == afterbegin ? 'first' : 'last') + 'Child';
513                     if (el.firstChild) {
514                         range[setStart](el[rangeEl]);
515                         frag = range.createContextualFragment(html);
516                         if(where == afterbegin){
517                             el.insertBefore(frag, el.firstChild);
518                         }else{
519                             el.appendChild(frag);
520                         }
521                     } else {
522                         el.innerHTML = html;
523                     }
524                     return el[rangeEl];
525                 }
526             }
527             throw 'Illegal insertion point -> "' + where + '"';
528         },
529
530         
531         insertBefore : function(el, o, returnElement){
532             return doInsert(el, o, returnElement, beforebegin);
533         },
534
535         
536         insertAfter : function(el, o, returnElement){
537             return doInsert(el, o, returnElement, afterend, 'nextSibling');
538         },
539
540         
541         insertFirst : function(el, o, returnElement){
542             return doInsert(el, o, returnElement, afterbegin, 'firstChild');
543         },
544
545         
546         append : function(el, o, returnElement){
547             return doInsert(el, o, returnElement, beforeend, '', true);
548         },
549
550         
551         overwrite : function(el, o, returnElement){
552             el = Ext.getDom(el);
553             el.innerHTML = createHtml(o);
554             return returnElement ? Ext.get(el.firstChild) : el.firstChild;
555         },
556
557         createHtml : createHtml
558     };
559     return pub;
560 }();
561
562 Ext.Template = function(html){
563     var me = this,
564         a = arguments,
565         buf = [],
566         v;
567
568     if (Ext.isArray(html)) {
569         html = html.join("");
570     } else if (a.length > 1) {
571         for(var i = 0, len = a.length; i < len; i++){
572             v = a[i];
573             if(typeof v == 'object'){
574                 Ext.apply(me, v);
575             } else {
576                 buf.push(v);
577             }
578         };
579         html = buf.join('');
580     }
581
582     
583     me.html = html;
584     
585     if (me.compiled) {
586         me.compile();
587     }
588 };
589 Ext.Template.prototype = {
590     
591     re : /\{([\w-]+)\}/g,
592     
593
594     
595     applyTemplate : function(values){
596         var me = this;
597
598         return me.compiled ?
599                 me.compiled(values) :
600                 me.html.replace(me.re, function(m, name){
601                     return values[name] !== undefined ? values[name] : "";
602                 });
603     },
604
605     
606     set : function(html, compile){
607         var me = this;
608         me.html = html;
609         me.compiled = null;
610         return compile ? me.compile() : me;
611     },
612
613     
614     compile : function(){
615         var me = this,
616             sep = Ext.isGecko ? "+" : ",";
617
618         function fn(m, name){
619             name = "values['" + name + "']";
620             return "'"+ sep + '(' + name + " == undefined ? '' : " + name + ')' + sep + "'";
621         }
622
623         eval("this.compiled = function(values){ return " + (Ext.isGecko ? "'" : "['") +
624              me.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
625              (Ext.isGecko ?  "';};" : "'].join('');};"));
626         return me;
627     },
628
629     
630     insertFirst: function(el, values, returnElement){
631         return this.doInsert('afterBegin', el, values, returnElement);
632     },
633
634     
635     insertBefore: function(el, values, returnElement){
636         return this.doInsert('beforeBegin', el, values, returnElement);
637     },
638
639     
640     insertAfter : function(el, values, returnElement){
641         return this.doInsert('afterEnd', el, values, returnElement);
642     },
643
644     
645     append : function(el, values, returnElement){
646         return this.doInsert('beforeEnd', el, values, returnElement);
647     },
648
649     doInsert : function(where, el, values, returnEl){
650         el = Ext.getDom(el);
651         var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
652         return returnEl ? Ext.get(newNode, true) : newNode;
653     },
654
655     
656     overwrite : function(el, values, returnElement){
657         el = Ext.getDom(el);
658         el.innerHTML = this.applyTemplate(values);
659         return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
660     }
661 };
662
663 Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
664
665
666 Ext.Template.from = function(el, config){
667     el = Ext.getDom(el);
668     return new Ext.Template(el.value || el.innerHTML, config || '');
669 };
670
671
672 Ext.DomQuery = function(){
673     var cache = {}, 
674         simpleCache = {}, 
675         valueCache = {},
676         nonSpace = /\S/,
677         trimRe = /^\s+|\s+$/g,
678         tplRe = /\{(\d+)\}/g,
679         modeRe = /^(\s?[\/>+~]\s?|\s|$)/,
680         tagTokenRe = /^(#)?([\w-\*]+)/,
681         nthRe = /(\d*)n\+?(\d*)/, 
682         nthRe2 = /\D/,
683         
684         
685         
686         isIE = window.ActiveXObject ? true : false,
687         key = 30803;
688     
689     
690     
691     eval("var batch = 30803;");         
692
693     
694     
695     function child(parent, index){
696         var i = 0,
697             n = parent.firstChild;
698         while(n){
699             if(n.nodeType == 1){
700                if(++i == index){
701                    return n;
702                }
703             }
704             n = n.nextSibling;
705         }
706         return null;
707     }
708
709     
710     function next(n){   
711         while((n = n.nextSibling) && n.nodeType != 1);
712         return n;
713     }
714
715     
716     function prev(n){
717         while((n = n.previousSibling) && n.nodeType != 1);
718         return n;
719     }
720
721     
722     
723     function children(parent){
724         var n = parent.firstChild,
725             nodeIndex = -1,
726             nextNode;
727         while(n){
728             nextNode = n.nextSibling;
729             
730             if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
731                 parent.removeChild(n);
732             }else{
733                 
734                 n.nodeIndex = ++nodeIndex;
735             }
736             n = nextNode;
737         }
738         return this;
739     }
740
741
742     
743     
744     function byClassName(nodeSet, cls){
745         if(!cls){
746             return nodeSet;
747         }
748         var result = [], ri = -1;
749         for(var i = 0, ci; ci = nodeSet[i]; i++){
750             if((' '+ci.className+' ').indexOf(cls) != -1){
751                 result[++ri] = ci;
752             }
753         }
754         return result;
755     };
756
757     function attrValue(n, attr){
758         
759         if(!n.tagName && typeof n.length != "undefined"){
760             n = n[0];
761         }
762         if(!n){
763             return null;
764         }
765
766         if(attr == "for"){
767             return n.htmlFor;
768         }
769         if(attr == "class" || attr == "className"){
770             return n.className;
771         }
772         return n.getAttribute(attr) || n[attr];
773
774     };
775
776
777     
778     
779     
780     function getNodes(ns, mode, tagName){
781         var result = [], ri = -1, cs;
782         if(!ns){
783             return result;
784         }
785         tagName = tagName || "*";
786         
787         if(typeof ns.getElementsByTagName != "undefined"){
788             ns = [ns];
789         }
790         
791         
792         
793         if(!mode){
794             for(var i = 0, ni; ni = ns[i]; i++){
795                 cs = ni.getElementsByTagName(tagName);
796                 for(var j = 0, ci; ci = cs[j]; j++){
797                     result[++ri] = ci;
798                 }
799             }
800         
801         
802         } else if(mode == "/" || mode == ">"){
803             var utag = tagName.toUpperCase();
804             for(var i = 0, ni, cn; ni = ns[i]; i++){
805                 cn = ni.childNodes;
806                 for(var j = 0, cj; cj = cn[j]; j++){
807                     if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){
808                         result[++ri] = cj;
809                     }
810                 }
811             }
812         
813         
814         }else if(mode == "+"){
815             var utag = tagName.toUpperCase();
816             for(var i = 0, n; n = ns[i]; i++){
817                 while((n = n.nextSibling) && n.nodeType != 1);
818                 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
819                     result[++ri] = n;
820                 }
821             }
822         
823         
824         }else if(mode == "~"){
825             var utag = tagName.toUpperCase();
826             for(var i = 0, n; n = ns[i]; i++){
827                 while((n = n.nextSibling)){
828                     if (n.nodeName == utag || n.nodeName == tagName || tagName == '*'){
829                         result[++ri] = n;
830                     }
831                 }
832             }
833         }
834         return result;
835     }
836
837     function concat(a, b){
838         if(b.slice){
839             return a.concat(b);
840         }
841         for(var i = 0, l = b.length; i < l; i++){
842             a[a.length] = b[i];
843         }
844         return a;
845     }
846
847     function byTag(cs, tagName){
848         if(cs.tagName || cs == document){
849             cs = [cs];
850         }
851         if(!tagName){
852             return cs;
853         }
854         var result = [], ri = -1;
855         tagName = tagName.toLowerCase();
856         for(var i = 0, ci; ci = cs[i]; i++){
857             if(ci.nodeType == 1 && ci.tagName.toLowerCase() == tagName){
858                 result[++ri] = ci;
859             }
860         }
861         return result;
862     }
863
864     function byId(cs, id){
865         if(cs.tagName || cs == document){
866             cs = [cs];
867         }
868         if(!id){
869             return cs;
870         }
871         var result = [], ri = -1;
872         for(var i = 0, ci; ci = cs[i]; i++){
873             if(ci && ci.id == id){
874                 result[++ri] = ci;
875                 return result;
876             }
877         }
878         return result;
879     }
880
881     
882     
883     function byAttribute(cs, attr, value, op, custom){
884         var result = [], 
885             ri = -1, 
886             useGetStyle = custom == "{",            
887             fn = Ext.DomQuery.operators[op],        
888             a,
889             xml,
890             hasXml;
891             
892         for(var i = 0, ci; ci = cs[i]; i++){
893             
894             if(ci.nodeType != 1){
895                 continue;
896             }
897             
898             if(!hasXml){
899                 xml = Ext.DomQuery.isXml(ci);
900                 hasXml = true;
901             }
902             
903             
904             if(!xml){
905                 if(useGetStyle){
906                     a = Ext.DomQuery.getStyle(ci, attr);
907                 } else if (attr == "class" || attr == "className"){
908                     a = ci.className;
909                 } else if (attr == "for"){
910                     a = ci.htmlFor;
911                 } else if (attr == "href"){
912                     
913                     
914                     a = ci.getAttribute("href", 2);
915                 } else{
916                     a = ci.getAttribute(attr);
917                 }
918             }else{
919                 a = ci.getAttribute(attr);
920             }
921             if((fn && fn(a, value)) || (!fn && a)){
922                 result[++ri] = ci;
923             }
924         }
925         return result;
926     }
927
928     function byPseudo(cs, name, value){
929         return Ext.DomQuery.pseudos[name](cs, value);
930     }
931
932     function nodupIEXml(cs){
933         var d = ++key, 
934             r;
935         cs[0].setAttribute("_nodup", d);
936         r = [cs[0]];
937         for(var i = 1, len = cs.length; i < len; i++){
938             var c = cs[i];
939             if(!c.getAttribute("_nodup") != d){
940                 c.setAttribute("_nodup", d);
941                 r[r.length] = c;
942             }
943         }
944         for(var i = 0, len = cs.length; i < len; i++){
945             cs[i].removeAttribute("_nodup");
946         }
947         return r;
948     }
949
950     function nodup(cs){
951         if(!cs){
952             return [];
953         }
954         var len = cs.length, c, i, r = cs, cj, ri = -1;
955         if(!len || typeof cs.nodeType != "undefined" || len == 1){
956             return cs;
957         }
958         if(isIE && typeof cs[0].selectSingleNode != "undefined"){
959             return nodupIEXml(cs);
960         }
961         var d = ++key;
962         cs[0]._nodup = d;
963         for(i = 1; c = cs[i]; i++){
964             if(c._nodup != d){
965                 c._nodup = d;
966             }else{
967                 r = [];
968                 for(var j = 0; j < i; j++){
969                     r[++ri] = cs[j];
970                 }
971                 for(j = i+1; cj = cs[j]; j++){
972                     if(cj._nodup != d){
973                         cj._nodup = d;
974                         r[++ri] = cj;
975                     }
976                 }
977                 return r;
978             }
979         }
980         return r;
981     }
982
983     function quickDiffIEXml(c1, c2){
984         var d = ++key,
985             r = [];
986         for(var i = 0, len = c1.length; i < len; i++){
987             c1[i].setAttribute("_qdiff", d);
988         }        
989         for(var i = 0, len = c2.length; i < len; i++){
990             if(c2[i].getAttribute("_qdiff") != d){
991                 r[r.length] = c2[i];
992             }
993         }
994         for(var i = 0, len = c1.length; i < len; i++){
995            c1[i].removeAttribute("_qdiff");
996         }
997         return r;
998     }
999
1000     function quickDiff(c1, c2){
1001         var len1 = c1.length,
1002                 d = ++key,
1003                 r = [];
1004         if(!len1){
1005             return c2;
1006         }
1007         if(isIE && typeof c1[0].selectSingleNode != "undefined"){
1008             return quickDiffIEXml(c1, c2);
1009         }        
1010         for(var i = 0; i < len1; i++){
1011             c1[i]._qdiff = d;
1012         }        
1013         for(var i = 0, len = c2.length; i < len; i++){
1014             if(c2[i]._qdiff != d){
1015                 r[r.length] = c2[i];
1016             }
1017         }
1018         return r;
1019     }
1020
1021     function quickId(ns, mode, root, id){
1022         if(ns == root){
1023            var d = root.ownerDocument || root;
1024            return d.getElementById(id);
1025         }
1026         ns = getNodes(ns, mode, "*");
1027         return byId(ns, id);
1028     }
1029
1030     return {
1031         getStyle : function(el, name){
1032             return Ext.fly(el).getStyle(name);
1033         },
1034         
1035         compile : function(path, type){
1036             type = type || "select";
1037
1038             
1039             var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"],
1040                         mode,           
1041                         lastPath,
1042                 matchers = Ext.DomQuery.matchers,
1043                 matchersLn = matchers.length,
1044                 modeMatch,
1045                 
1046                 lmode = path.match(modeRe);
1047             
1048             if(lmode && lmode[1]){
1049                 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
1050                 path = path.replace(lmode[1], "");
1051             }
1052             
1053             
1054             while(path.substr(0, 1)=="/"){
1055                 path = path.substr(1);
1056             }
1057
1058             while(path && lastPath != path){
1059                 lastPath = path;
1060                 var tokenMatch = path.match(tagTokenRe);
1061                 if(type == "select"){
1062                     if(tokenMatch){
1063                         
1064                         if(tokenMatch[1] == "#"){
1065                             fn[fn.length] = 'n = quickId(n, mode, root, "'+tokenMatch[2]+'");';                 
1066                         }else{
1067                             fn[fn.length] = 'n = getNodes(n, mode, "'+tokenMatch[2]+'");';
1068                         }
1069                         path = path.replace(tokenMatch[0], "");
1070                     }else if(path.substr(0, 1) != '@'){
1071                         fn[fn.length] = 'n = getNodes(n, mode, "*");';
1072                     }
1073                 
1074                 }else{
1075                     if(tokenMatch){
1076                         if(tokenMatch[1] == "#"){
1077                             fn[fn.length] = 'n = byId(n, "'+tokenMatch[2]+'");';
1078                         }else{
1079                             fn[fn.length] = 'n = byTag(n, "'+tokenMatch[2]+'");';
1080                         }
1081                         path = path.replace(tokenMatch[0], "");
1082                     }
1083                 }
1084                 while(!(modeMatch = path.match(modeRe))){
1085                     var matched = false;
1086                     for(var j = 0; j < matchersLn; j++){
1087                         var t = matchers[j];
1088                         var m = path.match(t.re);
1089                         if(m){
1090                             fn[fn.length] = t.select.replace(tplRe, function(x, i){
1091                                 return m[i];
1092                             });
1093                             path = path.replace(m[0], "");
1094                             matched = true;
1095                             break;
1096                         }
1097                     }
1098                     
1099                     if(!matched){
1100                         throw 'Error parsing selector, parsing failed at "' + path + '"';
1101                     }
1102                 }
1103                 if(modeMatch[1]){
1104                     fn[fn.length] = 'mode="'+modeMatch[1].replace(trimRe, "")+'";';
1105                     path = path.replace(modeMatch[1], "");
1106                 }
1107             }
1108             
1109             fn[fn.length] = "return nodup(n);\n}";
1110             
1111             
1112             eval(fn.join(""));
1113             return f;
1114         },
1115
1116         
1117         jsSelect: function(path, root, type){
1118             
1119             root = root || document;
1120             
1121             if(typeof root == "string"){
1122                 root = document.getElementById(root);
1123             }
1124             var paths = path.split(","),
1125                 results = [];
1126                 
1127             
1128             for(var i = 0, len = paths.length; i < len; i++){           
1129                 var subPath = paths[i].replace(trimRe, "");
1130                 
1131                 if(!cache[subPath]){
1132                     cache[subPath] = Ext.DomQuery.compile(subPath);
1133                     if(!cache[subPath]){
1134                         throw subPath + " is not a valid selector";
1135                     }
1136                 }
1137                 var result = cache[subPath](root);
1138                 if(result && result != document){
1139                     results = results.concat(result);
1140                 }
1141             }
1142             
1143             
1144             
1145             if(paths.length > 1){
1146                 return nodup(results);
1147             }
1148             return results;
1149         },
1150         isXml: function(el) {
1151             var docEl = (el ? el.ownerDocument || el : 0).documentElement;
1152             return docEl ? docEl.nodeName !== "HTML" : false;
1153         },
1154         select : document.querySelectorAll ? function(path, root, type) {
1155             root = root || document;
1156             if (!Ext.DomQuery.isXml(root)) {
1157                 try {
1158                     var cs = root.querySelectorAll(path);
1159                     return Ext.toArray(cs);
1160                 }
1161                 catch (ex) {}           
1162             }       
1163             return Ext.DomQuery.jsSelect.call(this, path, root, type);
1164         } : function(path, root, type) {
1165             return Ext.DomQuery.jsSelect.call(this, path, root, type);
1166         },
1167
1168         
1169         selectNode : function(path, root){
1170             return Ext.DomQuery.select(path, root)[0];
1171         },
1172
1173         
1174         selectValue : function(path, root, defaultValue){
1175             path = path.replace(trimRe, "");
1176             if(!valueCache[path]){
1177                 valueCache[path] = Ext.DomQuery.compile(path, "select");
1178             }
1179             var n = valueCache[path](root), v;
1180             n = n[0] ? n[0] : n;
1181                     
1182             
1183             
1184             
1185             
1186             if (typeof n.normalize == 'function') n.normalize();
1187             
1188             v = (n && n.firstChild ? n.firstChild.nodeValue : null);
1189             return ((v === null||v === undefined||v==='') ? defaultValue : v);
1190         },
1191
1192         
1193         selectNumber : function(path, root, defaultValue){
1194             var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);
1195             return parseFloat(v);
1196         },
1197
1198         
1199         is : function(el, ss){
1200             if(typeof el == "string"){
1201                 el = document.getElementById(el);
1202             }
1203             var isArray = Ext.isArray(el),
1204                 result = Ext.DomQuery.filter(isArray ? el : [el], ss);
1205             return isArray ? (result.length == el.length) : (result.length > 0);
1206         },
1207
1208         
1209         filter : function(els, ss, nonMatches){
1210             ss = ss.replace(trimRe, "");
1211             if(!simpleCache[ss]){
1212                 simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");
1213             }
1214             var result = simpleCache[ss](els);
1215             return nonMatches ? quickDiff(result, els) : result;
1216         },
1217
1218         
1219         matchers : [{
1220                 re: /^\.([\w-]+)/,
1221                 select: 'n = byClassName(n, " {1} ");'
1222             }, {
1223                 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
1224                 select: 'n = byPseudo(n, "{1}", "{2}");'
1225             },{
1226                 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
1227                 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
1228             }, {
1229                 re: /^#([\w-]+)/,
1230                 select: 'n = byId(n, "{1}");'
1231             },{
1232                 re: /^@([\w-]+)/,
1233                 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
1234             }
1235         ],
1236
1237         
1238         operators : {
1239             "=" : function(a, v){
1240                 return a == v;
1241             },
1242             "!=" : function(a, v){
1243                 return a != v;
1244             },
1245             "^=" : function(a, v){
1246                 return a && a.substr(0, v.length) == v;
1247             },
1248             "$=" : function(a, v){
1249                 return a && a.substr(a.length-v.length) == v;
1250             },
1251             "*=" : function(a, v){
1252                 return a && a.indexOf(v) !== -1;
1253             },
1254             "%=" : function(a, v){
1255                 return (a % v) == 0;
1256             },
1257             "|=" : function(a, v){
1258                 return a && (a == v || a.substr(0, v.length+1) == v+'-');
1259             },
1260             "~=" : function(a, v){
1261                 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
1262             }
1263         },
1264
1265         
1266         pseudos : {
1267             "first-child" : function(c){
1268                 var r = [], ri = -1, n;
1269                 for(var i = 0, ci; ci = n = c[i]; i++){
1270                     while((n = n.previousSibling) && n.nodeType != 1);
1271                     if(!n){
1272                         r[++ri] = ci;
1273                     }
1274                 }
1275                 return r;
1276             },
1277
1278             "last-child" : function(c){
1279                 var r = [], ri = -1, n;
1280                 for(var i = 0, ci; ci = n = c[i]; i++){
1281                     while((n = n.nextSibling) && n.nodeType != 1);
1282                     if(!n){
1283                         r[++ri] = ci;
1284                     }
1285                 }
1286                 return r;
1287             },
1288
1289             "nth-child" : function(c, a) {
1290                 var r = [], ri = -1,
1291                         m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a),
1292                         f = (m[1] || 1) - 0, l = m[2] - 0;
1293                 for(var i = 0, n; n = c[i]; i++){
1294                     var pn = n.parentNode;
1295                     if (batch != pn._batch) {
1296                         var j = 0;
1297                         for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
1298                             if(cn.nodeType == 1){
1299                                cn.nodeIndex = ++j;
1300                             }
1301                         }
1302                         pn._batch = batch;
1303                     }
1304                     if (f == 1) {
1305                         if (l == 0 || n.nodeIndex == l){
1306                             r[++ri] = n;
1307                         }
1308                     } else if ((n.nodeIndex + l) % f == 0){
1309                         r[++ri] = n;
1310                     }
1311                 }
1312
1313                 return r;
1314             },
1315
1316             "only-child" : function(c){
1317                 var r = [], ri = -1;;
1318                 for(var i = 0, ci; ci = c[i]; i++){
1319                     if(!prev(ci) && !next(ci)){
1320                         r[++ri] = ci;
1321                     }
1322                 }
1323                 return r;
1324             },
1325
1326             "empty" : function(c){
1327                 var r = [], ri = -1;
1328                 for(var i = 0, ci; ci = c[i]; i++){
1329                     var cns = ci.childNodes, j = 0, cn, empty = true;
1330                     while(cn = cns[j]){
1331                         ++j;
1332                         if(cn.nodeType == 1 || cn.nodeType == 3){
1333                             empty = false;
1334                             break;
1335                         }
1336                     }
1337                     if(empty){
1338                         r[++ri] = ci;
1339                     }
1340                 }
1341                 return r;
1342             },
1343
1344             "contains" : function(c, v){
1345                 var r = [], ri = -1;
1346                 for(var i = 0, ci; ci = c[i]; i++){
1347                     if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
1348                         r[++ri] = ci;
1349                     }
1350                 }
1351                 return r;
1352             },
1353
1354             "nodeValue" : function(c, v){
1355                 var r = [], ri = -1;
1356                 for(var i = 0, ci; ci = c[i]; i++){
1357                     if(ci.firstChild && ci.firstChild.nodeValue == v){
1358                         r[++ri] = ci;
1359                     }
1360                 }
1361                 return r;
1362             },
1363
1364             "checked" : function(c){
1365                 var r = [], ri = -1;
1366                 for(var i = 0, ci; ci = c[i]; i++){
1367                     if(ci.checked == true){
1368                         r[++ri] = ci;
1369                     }
1370                 }
1371                 return r;
1372             },
1373
1374             "not" : function(c, ss){
1375                 return Ext.DomQuery.filter(c, ss, true);
1376             },
1377
1378             "any" : function(c, selectors){
1379                 var ss = selectors.split('|'),
1380                         r = [], ri = -1, s;
1381                 for(var i = 0, ci; ci = c[i]; i++){
1382                     for(var j = 0; s = ss[j]; j++){
1383                         if(Ext.DomQuery.is(ci, s)){
1384                             r[++ri] = ci;
1385                             break;
1386                         }
1387                     }
1388                 }
1389                 return r;
1390             },
1391
1392             "odd" : function(c){
1393                 return this["nth-child"](c, "odd");
1394             },
1395
1396             "even" : function(c){
1397                 return this["nth-child"](c, "even");
1398             },
1399
1400             "nth" : function(c, a){
1401                 return c[a-1] || [];
1402             },
1403
1404             "first" : function(c){
1405                 return c[0] || [];
1406             },
1407
1408             "last" : function(c){
1409                 return c[c.length-1] || [];
1410             },
1411
1412             "has" : function(c, ss){
1413                 var s = Ext.DomQuery.select,
1414                         r = [], ri = -1;
1415                 for(var i = 0, ci; ci = c[i]; i++){
1416                     if(s(ss, ci).length > 0){
1417                         r[++ri] = ci;
1418                     }
1419                 }
1420                 return r;
1421             },
1422
1423             "next" : function(c, ss){
1424                 var is = Ext.DomQuery.is,
1425                         r = [], ri = -1;
1426                 for(var i = 0, ci; ci = c[i]; i++){
1427                     var n = next(ci);
1428                     if(n && is(n, ss)){
1429                         r[++ri] = ci;
1430                     }
1431                 }
1432                 return r;
1433             },
1434
1435             "prev" : function(c, ss){
1436                 var is = Ext.DomQuery.is,
1437                         r = [], ri = -1;
1438                 for(var i = 0, ci; ci = c[i]; i++){
1439                     var n = prev(ci);
1440                     if(n && is(n, ss)){
1441                         r[++ri] = ci;
1442                     }
1443                 }
1444                 return r;
1445             }
1446         }
1447     };
1448 }();
1449
1450
1451 Ext.query = Ext.DomQuery.select;
1452
1453 Ext.util.DelayedTask = function(fn, scope, args){
1454     var me = this,
1455         id,     
1456         call = function(){
1457                 clearInterval(id);
1458                 id = null;
1459                 fn.apply(scope, args || []);
1460             };
1461             
1462     
1463     me.delay = function(delay, newFn, newScope, newArgs){
1464         me.cancel();
1465         fn = newFn || fn;
1466         scope = newScope || scope;
1467         args = newArgs || args;
1468         id = setInterval(call, delay);
1469     };
1470
1471     
1472     me.cancel = function(){
1473         if(id){
1474             clearInterval(id);
1475             id = null;
1476         }
1477     };
1478 };
1479 (function(){
1480 var DOC = document;
1481
1482 Ext.Element = function(element, forceNew){
1483     var dom = typeof element == "string" ?
1484               DOC.getElementById(element) : element,
1485         id;
1486
1487     if(!dom) return null;
1488
1489     id = dom.id;
1490
1491     if(!forceNew && id && Ext.elCache[id]){ 
1492         return Ext.elCache[id].el;
1493     }
1494
1495     
1496     this.dom = dom;
1497
1498     
1499     this.id = id || Ext.id(dom);
1500 };
1501
1502 var DH = Ext.DomHelper,
1503     El = Ext.Element,
1504     EC = Ext.elCache;
1505
1506 El.prototype = {
1507     
1508     set : function(o, useSet){
1509         var el = this.dom,
1510             attr,
1511             val,
1512             useSet = (useSet !== false) && !!el.setAttribute;
1513
1514         for (attr in o) {
1515             if (o.hasOwnProperty(attr)) {
1516                 val = o[attr];
1517                 if (attr == 'style') {
1518                     DH.applyStyles(el, val);
1519                 } else if (attr == 'cls') {
1520                     el.className = val;
1521                 } else if (useSet) {
1522                     el.setAttribute(attr, val);
1523                 } else {
1524                     el[attr] = val;
1525                 }
1526             }
1527         }
1528         return this;
1529     },
1530
1531
1532     
1533     
1534     
1535     
1536     
1537     
1538     
1539     
1540     
1541     
1542
1543
1544     
1545     
1546     
1547
1548
1549
1550     
1551     
1552     
1553     
1554     
1555     
1556
1557
1558     
1559     
1560     
1561     
1562     
1563     
1564
1565
1566     
1567     
1568     
1569
1570
1571     
1572     
1573     
1574     
1575     
1576     
1577     
1578
1579     
1580     defaultUnit : "px",
1581
1582     
1583     is : function(simpleSelector){
1584         return Ext.DomQuery.is(this.dom, simpleSelector);
1585     },
1586
1587     
1588     focus : function(defer,  dom) {
1589         var me = this,
1590             dom = dom || me.dom;
1591         try{
1592             if(Number(defer)){
1593                 me.focus.defer(defer, null, [null, dom]);
1594             }else{
1595                 dom.focus();
1596             }
1597         }catch(e){}
1598         return me;
1599     },
1600
1601     
1602     blur : function() {
1603         try{
1604             this.dom.blur();
1605         }catch(e){}
1606         return this;
1607     },
1608
1609     
1610     getValue : function(asNumber){
1611         var val = this.dom.value;
1612         return asNumber ? parseInt(val, 10) : val;
1613     },
1614
1615     
1616     addListener : function(eventName, fn, scope, options){
1617         Ext.EventManager.on(this.dom,  eventName, fn, scope || this, options);
1618         return this;
1619     },
1620
1621     
1622     removeListener : function(eventName, fn, scope){
1623         Ext.EventManager.removeListener(this.dom,  eventName, fn, scope || this);
1624         return this;
1625     },
1626
1627     
1628     removeAllListeners : function(){
1629         Ext.EventManager.removeAll(this.dom);
1630         return this;
1631     },
1632
1633     
1634     purgeAllListeners : function() {
1635         Ext.EventManager.purgeElement(this, true);
1636         return this;
1637     },
1638     
1639     addUnits : function(size){
1640         if(size === "" || size == "auto" || size === undefined){
1641             size = size || '';
1642         } else if(!isNaN(size) || !unitPattern.test(size)){
1643             size = size + (this.defaultUnit || 'px');
1644         }
1645         return size;
1646     },
1647
1648     
1649     load : function(url, params, cb){
1650         Ext.Ajax.request(Ext.apply({
1651             params: params,
1652             url: url.url || url,
1653             callback: cb,
1654             el: this.dom,
1655             indicatorText: url.indicatorText || ''
1656         }, Ext.isObject(url) ? url : {}));
1657         return this;
1658     },
1659
1660     
1661     isBorderBox : function(){
1662         return Ext.isBorderBox || Ext.isForcedBorderBox || noBoxAdjust[(this.dom.tagName || "").toLowerCase()];
1663     },
1664
1665     
1666     remove : function(){
1667         var me = this,
1668             dom = me.dom;
1669
1670         if (dom) {
1671             delete me.dom;
1672             Ext.removeNode(dom);
1673         }
1674     },
1675
1676     
1677     hover : function(overFn, outFn, scope, options){
1678         var me = this;
1679         me.on('mouseenter', overFn, scope || me.dom, options);
1680         me.on('mouseleave', outFn, scope || me.dom, options);
1681         return me;
1682     },
1683
1684     
1685     contains : function(el){
1686         return !el ? false : Ext.lib.Dom.isAncestor(this.dom, el.dom ? el.dom : el);
1687     },
1688
1689     
1690     getAttributeNS : function(ns, name){
1691         return this.getAttribute(name, ns);
1692     },
1693
1694     
1695     getAttribute : Ext.isIE ? function(name, ns){
1696         var d = this.dom,
1697             type = typeof d[ns + ":" + name];
1698
1699         if(['undefined', 'unknown'].indexOf(type) == -1){
1700             return d[ns + ":" + name];
1701         }
1702         return d[name];
1703     } : function(name, ns){
1704         var d = this.dom;
1705         return d.getAttributeNS(ns, name) || d.getAttribute(ns + ":" + name) || d.getAttribute(name) || d[name];
1706     },
1707
1708     
1709     update : function(html) {
1710         if (this.dom) {
1711             this.dom.innerHTML = html;
1712         }
1713         return this;
1714     }
1715 };
1716
1717 var ep = El.prototype;
1718
1719 El.addMethods = function(o){
1720    Ext.apply(ep, o);
1721 };
1722
1723
1724 ep.on = ep.addListener;
1725
1726
1727 ep.un = ep.removeListener;
1728
1729
1730 ep.autoBoxAdjust = true;
1731
1732
1733 var unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
1734     docEl;
1735
1736
1737
1738
1739 El.get = function(el){
1740     var ex,
1741         elm,
1742         id;
1743     if(!el){ return null; }
1744     if (typeof el == "string") { 
1745         if (!(elm = DOC.getElementById(el))) {
1746             return null;
1747         }
1748         if (EC[el] && EC[el].el) {
1749             ex = EC[el].el;
1750             ex.dom = elm;
1751         } else {
1752             ex = El.addToCache(new El(elm));
1753         }
1754         return ex;
1755     } else if (el.tagName) { 
1756         if(!(id = el.id)){
1757             id = Ext.id(el);
1758         }
1759         if (EC[id] && EC[id].el) {
1760             ex = EC[id].el;
1761             ex.dom = el;
1762         } else {
1763             ex = El.addToCache(new El(el));
1764         }
1765         return ex;
1766     } else if (el instanceof El) {
1767         if(el != docEl){
1768             
1769             
1770
1771             
1772             if (Ext.isIE && (el.id == undefined || el.id == '')) {
1773                 el.dom = el.dom;
1774             } else {
1775                 el.dom = DOC.getElementById(el.id) || el.dom;
1776             }
1777         }
1778         return el;
1779     } else if(el.isComposite) {
1780         return el;
1781     } else if(Ext.isArray(el)) {
1782         return El.select(el);
1783     } else if(el == DOC) {
1784         
1785         if(!docEl){
1786             var f = function(){};
1787             f.prototype = El.prototype;
1788             docEl = new f();
1789             docEl.dom = DOC;
1790         }
1791         return docEl;
1792     }
1793     return null;
1794 };
1795
1796 El.addToCache = function(el, id){
1797     id = id || el.id;
1798     EC[id] = {
1799         el:  el,
1800         data: {},
1801         events: {}
1802     };
1803     return el;
1804 };
1805
1806
1807 El.data = function(el, key, value){
1808     el = El.get(el);
1809     if (!el) {
1810         return null;
1811     }
1812     var c = EC[el.id].data;
1813     if(arguments.length == 2){
1814         return c[key];
1815     }else{
1816         return (c[key] = value);
1817     }
1818 };
1819
1820
1821
1822
1823 function garbageCollect(){
1824     if(!Ext.enableGarbageCollector){
1825         clearInterval(El.collectorThreadId);
1826     } else {
1827         var eid,
1828             el,
1829             d,
1830             o;
1831
1832         for(eid in EC){
1833             o = EC[eid];
1834             if(o.skipGC){
1835                 continue;
1836             }
1837             el = o.el;
1838             d = el.dom;
1839             
1840             
1841             
1842             
1843             
1844             
1845             
1846             
1847             
1848             
1849             
1850             
1851             
1852             
1853             
1854             
1855             
1856             if(!d || !d.parentNode || (!d.offsetParent && !DOC.getElementById(eid))){
1857                 if(Ext.enableListenerCollection){
1858                     Ext.EventManager.removeAll(d);
1859                 }
1860                 delete EC[eid];
1861             }
1862         }
1863         
1864         if (Ext.isIE) {
1865             var t = {};
1866             for (eid in EC) {
1867                 t[eid] = EC[eid];
1868             }
1869             EC = Ext.elCache = t;
1870         }
1871     }
1872 }
1873 El.collectorThreadId = setInterval(garbageCollect, 30000);
1874
1875 var flyFn = function(){};
1876 flyFn.prototype = El.prototype;
1877
1878
1879 El.Flyweight = function(dom){
1880     this.dom = dom;
1881 };
1882
1883 El.Flyweight.prototype = new flyFn();
1884 El.Flyweight.prototype.isFlyweight = true;
1885 El._flyweights = {};
1886
1887
1888 El.fly = function(el, named){
1889     var ret = null;
1890     named = named || '_global';
1891
1892     if (el = Ext.getDom(el)) {
1893         (El._flyweights[named] = El._flyweights[named] || new El.Flyweight()).dom = el;
1894         ret = El._flyweights[named];
1895     }
1896     return ret;
1897 };
1898
1899
1900 Ext.get = El.get;
1901
1902
1903 Ext.fly = El.fly;
1904
1905
1906 var noBoxAdjust = Ext.isStrict ? {
1907     select:1
1908 } : {
1909     input:1, select:1, textarea:1
1910 };
1911 if(Ext.isIE || Ext.isGecko){
1912     noBoxAdjust['button'] = 1;
1913 }
1914
1915 })();
1916
1917 Ext.Element.addMethods(function(){
1918         var PARENTNODE = 'parentNode',
1919                 NEXTSIBLING = 'nextSibling',
1920                 PREVIOUSSIBLING = 'previousSibling',
1921                 DQ = Ext.DomQuery,
1922                 GET = Ext.get;
1923         
1924         return {
1925                 
1926             findParent : function(simpleSelector, maxDepth, returnEl){
1927                 var p = this.dom,
1928                         b = document.body, 
1929                         depth = 0,                      
1930                         stopEl;         
1931             if(Ext.isGecko && Object.prototype.toString.call(p) == '[object XULElement]') {
1932                 return null;
1933             }
1934                 maxDepth = maxDepth || 50;
1935                 if (isNaN(maxDepth)) {
1936                     stopEl = Ext.getDom(maxDepth);
1937                     maxDepth = Number.MAX_VALUE;
1938                 }
1939                 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
1940                     if(DQ.is(p, simpleSelector)){
1941                         return returnEl ? GET(p) : p;
1942                     }
1943                     depth++;
1944                     p = p.parentNode;
1945                 }
1946                 return null;
1947             },
1948         
1949             
1950             findParentNode : function(simpleSelector, maxDepth, returnEl){
1951                 var p = Ext.fly(this.dom.parentNode, '_internal');
1952                 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
1953             },
1954         
1955             
1956             up : function(simpleSelector, maxDepth){
1957                 return this.findParentNode(simpleSelector, maxDepth, true);
1958             },
1959         
1960             
1961             select : function(selector){
1962                 return Ext.Element.select(selector, this.dom);
1963             },
1964         
1965             
1966             query : function(selector){
1967                 return DQ.select(selector, this.dom);
1968             },
1969         
1970             
1971             child : function(selector, returnDom){
1972                 var n = DQ.selectNode(selector, this.dom);
1973                 return returnDom ? n : GET(n);
1974             },
1975         
1976             
1977             down : function(selector, returnDom){
1978                 var n = DQ.selectNode(" > " + selector, this.dom);
1979                 return returnDom ? n : GET(n);
1980             },
1981         
1982                  
1983             parent : function(selector, returnDom){
1984                 return this.matchNode(PARENTNODE, PARENTNODE, selector, returnDom);
1985             },
1986         
1987              
1988             next : function(selector, returnDom){
1989                 return this.matchNode(NEXTSIBLING, NEXTSIBLING, selector, returnDom);
1990             },
1991         
1992             
1993             prev : function(selector, returnDom){
1994                 return this.matchNode(PREVIOUSSIBLING, PREVIOUSSIBLING, selector, returnDom);
1995             },
1996         
1997         
1998             
1999             first : function(selector, returnDom){
2000                 return this.matchNode(NEXTSIBLING, 'firstChild', selector, returnDom);
2001             },
2002         
2003             
2004             last : function(selector, returnDom){
2005                 return this.matchNode(PREVIOUSSIBLING, 'lastChild', selector, returnDom);
2006             },
2007             
2008             matchNode : function(dir, start, selector, returnDom){
2009                 var n = this.dom[start];
2010                 while(n){
2011                     if(n.nodeType == 1 && (!selector || DQ.is(n, selector))){
2012                         return !returnDom ? GET(n) : n;
2013                     }
2014                     n = n[dir];
2015                 }
2016                 return null;
2017             }   
2018     };
2019 }());
2020 Ext.Element.addMethods(
2021 function() {
2022         var GETDOM = Ext.getDom,
2023                 GET = Ext.get,
2024                 DH = Ext.DomHelper;
2025         
2026         return {
2027             
2028             appendChild: function(el){        
2029                 return GET(el).appendTo(this);        
2030             },
2031         
2032             
2033             appendTo: function(el){        
2034                 GETDOM(el).appendChild(this.dom);        
2035                 return this;
2036             },
2037         
2038             
2039             insertBefore: function(el){                   
2040                 (el = GETDOM(el)).parentNode.insertBefore(this.dom, el);
2041                 return this;
2042             },
2043         
2044             
2045             insertAfter: function(el){
2046                 (el = GETDOM(el)).parentNode.insertBefore(this.dom, el.nextSibling);
2047                 return this;
2048             },
2049         
2050             
2051             insertFirst: function(el, returnDom){
2052             el = el || {};
2053             if(el.nodeType || el.dom || typeof el == 'string'){ 
2054                 el = GETDOM(el);
2055                 this.dom.insertBefore(el, this.dom.firstChild);
2056                 return !returnDom ? GET(el) : el;
2057             }else{ 
2058                 return this.createChild(el, this.dom.firstChild, returnDom);
2059             }
2060         },
2061         
2062             
2063             replace: function(el){
2064                 el = GET(el);
2065                 this.insertBefore(el);
2066                 el.remove();
2067                 return this;
2068             },
2069         
2070             
2071             replaceWith: function(el){
2072                     var me = this;
2073                 
2074             if(el.nodeType || el.dom || typeof el == 'string'){
2075                 el = GETDOM(el);
2076                 me.dom.parentNode.insertBefore(el, me.dom);
2077             }else{
2078                 el = DH.insertBefore(me.dom, el);
2079             }
2080                 
2081                 delete Ext.elCache[me.id];
2082                 Ext.removeNode(me.dom);      
2083                 me.id = Ext.id(me.dom = el);
2084                 Ext.Element.addToCache(me.isFlyweight ? new Ext.Element(me.dom) : me);     
2085             return me;
2086             },
2087             
2088                 
2089                 createChild: function(config, insertBefore, returnDom){
2090                     config = config || {tag:'div'};
2091                     return insertBefore ? 
2092                            DH.insertBefore(insertBefore, config, returnDom !== true) :  
2093                            DH[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config,  returnDom !== true);
2094                 },
2095                 
2096                 
2097                 wrap: function(config, returnDom){        
2098                     var newEl = DH.insertBefore(this.dom, config || {tag: "div"}, !returnDom);
2099                     newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
2100                     return newEl;
2101                 },
2102                 
2103                 
2104                 insertHtml : function(where, html, returnEl){
2105                     var el = DH.insertHtml(where, this.dom, html);
2106                     return returnEl ? Ext.get(el) : el;
2107                 }
2108         };
2109 }());
2110 Ext.Element.addMethods(function(){
2111     
2112     var supports = Ext.supports,
2113         propCache = {},
2114         camelRe = /(-[a-z])/gi,
2115         view = document.defaultView,
2116         opacityRe = /alpha\(opacity=(.*)\)/i,
2117         trimRe = /^\s+|\s+$/g,
2118         EL = Ext.Element,
2119         spacesRe = /\s+/,
2120         wordsRe = /\w/g,
2121         PADDING = "padding",
2122         MARGIN = "margin",
2123         BORDER = "border",
2124         LEFT = "-left",
2125         RIGHT = "-right",
2126         TOP = "-top",
2127         BOTTOM = "-bottom",
2128         WIDTH = "-width",
2129         MATH = Math,
2130         HIDDEN = 'hidden',
2131         ISCLIPPED = 'isClipped',
2132         OVERFLOW = 'overflow',
2133         OVERFLOWX = 'overflow-x',
2134         OVERFLOWY = 'overflow-y',
2135         ORIGINALCLIP = 'originalClip',
2136         
2137         borders = {l: BORDER + LEFT + WIDTH, r: BORDER + RIGHT + WIDTH, t: BORDER + TOP + WIDTH, b: BORDER + BOTTOM + WIDTH},
2138         paddings = {l: PADDING + LEFT, r: PADDING + RIGHT, t: PADDING + TOP, b: PADDING + BOTTOM},
2139         margins = {l: MARGIN + LEFT, r: MARGIN + RIGHT, t: MARGIN + TOP, b: MARGIN + BOTTOM},
2140         data = Ext.Element.data;
2141
2142
2143     
2144     function camelFn(m, a) {
2145         return a.charAt(1).toUpperCase();
2146     }
2147
2148     function chkCache(prop) {
2149         return propCache[prop] || (propCache[prop] = prop == 'float' ? (supports.cssFloat ? 'cssFloat' : 'styleFloat') : prop.replace(camelRe, camelFn));
2150     }
2151
2152     return {
2153         
2154         adjustWidth : function(width) {
2155             var me = this;
2156             var isNum = (typeof width == "number");
2157             if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
2158                width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
2159             }
2160             return (isNum && width < 0) ? 0 : width;
2161         },
2162
2163         
2164         adjustHeight : function(height) {
2165             var me = this;
2166             var isNum = (typeof height == "number");
2167             if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
2168                height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
2169             }
2170             return (isNum && height < 0) ? 0 : height;
2171         },
2172
2173
2174         
2175         addClass : function(className){
2176             var me = this,
2177                 i,
2178                 len,
2179                 v,
2180                 cls = [];
2181             
2182             if (!Ext.isArray(className)) {
2183                 if (typeof className == 'string' && !this.hasClass(className)) {
2184                     me.dom.className += " " + className;
2185                 }
2186             }
2187             else {
2188                 for (i = 0, len = className.length; i < len; i++) {
2189                     v = className[i];
2190                     if (typeof v == 'string' && (' ' + me.dom.className + ' ').indexOf(' ' + v + ' ') == -1) {
2191                         cls.push(v);
2192                     }
2193                 }
2194                 if (cls.length) {
2195                     me.dom.className += " " + cls.join(" ");
2196                 }
2197             }
2198             return me;
2199         },
2200
2201         
2202         removeClass : function(className){
2203             var me = this,
2204                 i,
2205                 idx,
2206                 len,
2207                 cls,
2208                 elClasses;
2209             if (!Ext.isArray(className)){
2210                 className = [className];
2211             }
2212             if (me.dom && me.dom.className) {
2213                 elClasses = me.dom.className.replace(trimRe, '').split(spacesRe);
2214                 for (i = 0, len = className.length; i < len; i++) {
2215                     cls = className[i];
2216                     if (typeof cls == 'string') {
2217                         cls = cls.replace(trimRe, '');
2218                         idx = elClasses.indexOf(cls);
2219                         if (idx != -1) {
2220                             elClasses.splice(idx, 1);
2221                         }
2222                     }
2223                 }
2224                 me.dom.className = elClasses.join(" ");
2225             }
2226             return me;
2227         },
2228
2229         
2230         radioClass : function(className){
2231             var cn = this.dom.parentNode.childNodes,
2232                 v,
2233                 i,
2234                 len;
2235             className = Ext.isArray(className) ? className : [className];
2236             for (i = 0, len = cn.length; i < len; i++) {
2237                 v = cn[i];
2238                 if (v && v.nodeType == 1) {
2239                     Ext.fly(v, '_internal').removeClass(className);
2240                 }
2241             };
2242             return this.addClass(className);
2243         },
2244
2245         
2246         toggleClass : function(className){
2247             return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
2248         },
2249
2250         
2251         hasClass : function(className){
2252             return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
2253         },
2254
2255         
2256         replaceClass : function(oldClassName, newClassName){
2257             return this.removeClass(oldClassName).addClass(newClassName);
2258         },
2259
2260         isStyle : function(style, val) {
2261             return this.getStyle(style) == val;
2262         },
2263
2264         
2265         getStyle : function(){
2266             return view && view.getComputedStyle ?
2267                 function(prop){
2268                     var el = this.dom,
2269                         v,
2270                         cs,
2271                         out,
2272                         display;
2273
2274                     if(el == document){
2275                         return null;
2276                     }
2277                     prop = chkCache(prop);
2278                     out = (v = el.style[prop]) ? v :
2279                            (cs = view.getComputedStyle(el, "")) ? cs[prop] : null;
2280                            
2281                     
2282                     
2283                     if(prop == 'marginRight' && out != '0px' && !supports.correctRightMargin){
2284                         display = el.style.display;
2285                         el.style.display = 'inline-block';
2286                         out = view.getComputedStyle(el, '').marginRight;
2287                         el.style.display = display;
2288                     }
2289                     
2290                     if(prop == 'backgroundColor' && out == 'rgba(0, 0, 0, 0)' && !supports.correctTransparentColor){
2291                         out = 'transparent';
2292                     }
2293                     return out;
2294                 } :
2295                 function(prop){
2296                     var el = this.dom,
2297                         m,
2298                         cs;
2299
2300                     if(el == document) return null;
2301                     if (prop == 'opacity') {
2302                         if (el.style.filter.match) {
2303                             if(m = el.style.filter.match(opacityRe)){
2304                                 var fv = parseFloat(m[1]);
2305                                 if(!isNaN(fv)){
2306                                     return fv ? fv / 100 : 0;
2307                                 }
2308                             }
2309                         }
2310                         return 1;
2311                     }
2312                     prop = chkCache(prop);
2313                     return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
2314                 };
2315         }(),
2316
2317         
2318         getColor : function(attr, defaultValue, prefix){
2319             var v = this.getStyle(attr),
2320                 color = (typeof prefix != 'undefined') ? prefix : '#',
2321                 h;
2322
2323             if(!v || (/transparent|inherit/.test(v))) {
2324                 return defaultValue;
2325             }
2326             if(/^r/.test(v)){
2327                 Ext.each(v.slice(4, v.length -1).split(','), function(s){
2328                     h = parseInt(s, 10);
2329                     color += (h < 16 ? '0' : '') + h.toString(16);
2330                 });
2331             }else{
2332                 v = v.replace('#', '');
2333                 color += v.length == 3 ? v.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : v;
2334             }
2335             return(color.length > 5 ? color.toLowerCase() : defaultValue);
2336         },
2337
2338         
2339         setStyle : function(prop, value){
2340             var tmp, style;
2341             
2342             if (typeof prop != 'object') {
2343                 tmp = {};
2344                 tmp[prop] = value;
2345                 prop = tmp;
2346             }
2347             for (style in prop) {
2348                 value = prop[style];
2349                 style == 'opacity' ?
2350                     this.setOpacity(value) :
2351                     this.dom.style[chkCache(style)] = value;
2352             }
2353             return this;
2354         },
2355
2356         
2357          setOpacity : function(opacity, animate){
2358             var me = this,
2359                 s = me.dom.style;
2360
2361             if(!animate || !me.anim){
2362                 if(Ext.isIE){
2363                     var opac = opacity < 1 ? 'alpha(opacity=' + opacity * 100 + ')' : '',
2364                     val = s.filter.replace(opacityRe, '').replace(trimRe, '');
2365
2366                     s.zoom = 1;
2367                     s.filter = val + (val.length > 0 ? ' ' : '') + opac;
2368                 }else{
2369                     s.opacity = opacity;
2370                 }
2371             }else{
2372                 me.anim({opacity: {to: opacity}}, me.preanim(arguments, 1), null, .35, 'easeIn');
2373             }
2374             return me;
2375         },
2376
2377         
2378         clearOpacity : function(){
2379             var style = this.dom.style;
2380             if(Ext.isIE){
2381                 if(!Ext.isEmpty(style.filter)){
2382                     style.filter = style.filter.replace(opacityRe, '').replace(trimRe, '');
2383                 }
2384             }else{
2385                 style.opacity = style['-moz-opacity'] = style['-khtml-opacity'] = '';
2386             }
2387             return this;
2388         },
2389
2390         
2391         getHeight : function(contentHeight){
2392             var me = this,
2393                 dom = me.dom,
2394                 hidden = Ext.isIE && me.isStyle('display', 'none'),
2395                 h = MATH.max(dom.offsetHeight, hidden ? 0 : dom.clientHeight) || 0;
2396
2397             h = !contentHeight ? h : h - me.getBorderWidth("tb") - me.getPadding("tb");
2398             return h < 0 ? 0 : h;
2399         },
2400
2401         
2402         getWidth : function(contentWidth){
2403             var me = this,
2404                 dom = me.dom,
2405                 hidden = Ext.isIE && me.isStyle('display', 'none'),
2406                 w = MATH.max(dom.offsetWidth, hidden ? 0 : dom.clientWidth) || 0;
2407             w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");
2408             return w < 0 ? 0 : w;
2409         },
2410
2411         
2412         setWidth : function(width, animate){
2413             var me = this;
2414             width = me.adjustWidth(width);
2415             !animate || !me.anim ?
2416                 me.dom.style.width = me.addUnits(width) :
2417                 me.anim({width : {to : width}}, me.preanim(arguments, 1));
2418             return me;
2419         },
2420
2421         
2422          setHeight : function(height, animate){
2423             var me = this;
2424             height = me.adjustHeight(height);
2425             !animate || !me.anim ?
2426                 me.dom.style.height = me.addUnits(height) :
2427                 me.anim({height : {to : height}}, me.preanim(arguments, 1));
2428             return me;
2429         },
2430
2431         
2432         getBorderWidth : function(side){
2433             return this.addStyles(side, borders);
2434         },
2435
2436         
2437         getPadding : function(side){
2438             return this.addStyles(side, paddings);
2439         },
2440
2441         
2442         clip : function(){
2443             var me = this,
2444                 dom = me.dom;
2445
2446             if(!data(dom, ISCLIPPED)){
2447                 data(dom, ISCLIPPED, true);
2448                 data(dom, ORIGINALCLIP, {
2449                     o: me.getStyle(OVERFLOW),
2450                     x: me.getStyle(OVERFLOWX),
2451                     y: me.getStyle(OVERFLOWY)
2452                 });
2453                 me.setStyle(OVERFLOW, HIDDEN);
2454                 me.setStyle(OVERFLOWX, HIDDEN);
2455                 me.setStyle(OVERFLOWY, HIDDEN);
2456             }
2457             return me;
2458         },
2459
2460         
2461         unclip : function(){
2462             var me = this,
2463                 dom = me.dom;
2464
2465             if(data(dom, ISCLIPPED)){
2466                 data(dom, ISCLIPPED, false);
2467                 var o = data(dom, ORIGINALCLIP);
2468                 if(o.o){
2469                     me.setStyle(OVERFLOW, o.o);
2470                 }
2471                 if(o.x){
2472                     me.setStyle(OVERFLOWX, o.x);
2473                 }
2474                 if(o.y){
2475                     me.setStyle(OVERFLOWY, o.y);
2476                 }
2477             }
2478             return me;
2479         },
2480
2481         
2482         addStyles : function(sides, styles){
2483             var ttlSize = 0,
2484                 sidesArr = sides.match(wordsRe),
2485                 side,
2486                 size,
2487                 i,
2488                 len = sidesArr.length;
2489             for (i = 0; i < len; i++) {
2490                 side = sidesArr[i];
2491                 size = side && parseInt(this.getStyle(styles[side]), 10);
2492                 if (size) {
2493                     ttlSize += MATH.abs(size);
2494                 }
2495             }
2496             return ttlSize;
2497         },
2498
2499         margins : margins
2500     };
2501 }()
2502 );
2503
2504 (function(){
2505 var D = Ext.lib.Dom,
2506         LEFT = "left",
2507         RIGHT = "right",
2508         TOP = "top",
2509         BOTTOM = "bottom",
2510         POSITION = "position",
2511         STATIC = "static",
2512         RELATIVE = "relative",
2513         AUTO = "auto",
2514         ZINDEX = "z-index";
2515
2516 Ext.Element.addMethods({
2517         
2518     getX : function(){
2519         return D.getX(this.dom);
2520     },
2521
2522     
2523     getY : function(){
2524         return D.getY(this.dom);
2525     },
2526
2527     
2528     getXY : function(){
2529         return D.getXY(this.dom);
2530     },
2531
2532     
2533     getOffsetsTo : function(el){
2534         var o = this.getXY(),
2535                 e = Ext.fly(el, '_internal').getXY();
2536         return [o[0]-e[0],o[1]-e[1]];
2537     },
2538
2539     
2540     setX : function(x, animate){            
2541             return this.setXY([x, this.getY()], this.animTest(arguments, animate, 1));
2542     },
2543
2544     
2545     setY : function(y, animate){            
2546             return this.setXY([this.getX(), y], this.animTest(arguments, animate, 1));
2547     },
2548
2549     
2550     setLeft : function(left){
2551         this.setStyle(LEFT, this.addUnits(left));
2552         return this;
2553     },
2554
2555     
2556     setTop : function(top){
2557         this.setStyle(TOP, this.addUnits(top));
2558         return this;
2559     },
2560
2561     
2562     setRight : function(right){
2563         this.setStyle(RIGHT, this.addUnits(right));
2564         return this;
2565     },
2566
2567     
2568     setBottom : function(bottom){
2569         this.setStyle(BOTTOM, this.addUnits(bottom));
2570         return this;
2571     },
2572
2573     
2574     setXY : function(pos, animate){
2575             var me = this;
2576         if(!animate || !me.anim){
2577             D.setXY(me.dom, pos);
2578         }else{
2579             me.anim({points: {to: pos}}, me.preanim(arguments, 1), 'motion');
2580         }
2581         return me;
2582     },
2583
2584     
2585     setLocation : function(x, y, animate){
2586         return this.setXY([x, y], this.animTest(arguments, animate, 2));
2587     },
2588
2589     
2590     moveTo : function(x, y, animate){
2591         return this.setXY([x, y], this.animTest(arguments, animate, 2));        
2592     },    
2593     
2594     
2595     getLeft : function(local){
2596             return !local ? this.getX() : parseInt(this.getStyle(LEFT), 10) || 0;
2597     },
2598
2599     
2600     getRight : function(local){
2601             var me = this;
2602             return !local ? me.getX() + me.getWidth() : (me.getLeft(true) + me.getWidth()) || 0;
2603     },
2604
2605     
2606     getTop : function(local) {
2607             return !local ? this.getY() : parseInt(this.getStyle(TOP), 10) || 0;
2608     },
2609
2610     
2611     getBottom : function(local){
2612             var me = this;
2613             return !local ? me.getY() + me.getHeight() : (me.getTop(true) + me.getHeight()) || 0;
2614     },
2615
2616     
2617     position : function(pos, zIndex, x, y){
2618             var me = this;
2619             
2620         if(!pos && me.isStyle(POSITION, STATIC)){           
2621             me.setStyle(POSITION, RELATIVE);           
2622         } else if(pos) {
2623             me.setStyle(POSITION, pos);
2624         }
2625         if(zIndex){
2626             me.setStyle(ZINDEX, zIndex);
2627         }
2628         if(x || y) me.setXY([x || false, y || false]);
2629     },
2630
2631     
2632     clearPositioning : function(value){
2633         value = value || '';
2634         this.setStyle({
2635             left : value,
2636             right : value,
2637             top : value,
2638             bottom : value,
2639             "z-index" : "",
2640             position : STATIC
2641         });
2642         return this;
2643     },
2644
2645     
2646     getPositioning : function(){
2647         var l = this.getStyle(LEFT);
2648         var t = this.getStyle(TOP);
2649         return {
2650             "position" : this.getStyle(POSITION),
2651             "left" : l,
2652             "right" : l ? "" : this.getStyle(RIGHT),
2653             "top" : t,
2654             "bottom" : t ? "" : this.getStyle(BOTTOM),
2655             "z-index" : this.getStyle(ZINDEX)
2656         };
2657     },
2658     
2659     
2660     setPositioning : function(pc){
2661             var me = this,
2662                 style = me.dom.style;
2663                 
2664         me.setStyle(pc);
2665         
2666         if(pc.right == AUTO){
2667             style.right = "";
2668         }
2669         if(pc.bottom == AUTO){
2670             style.bottom = "";
2671         }
2672         
2673         return me;
2674     },    
2675         
2676     
2677     translatePoints : function(x, y){                
2678             y = isNaN(x[1]) ? y : x[1];
2679         x = isNaN(x[0]) ? x : x[0];
2680         var me = this,
2681                 relative = me.isStyle(POSITION, RELATIVE),
2682                 o = me.getXY(),
2683                 l = parseInt(me.getStyle(LEFT), 10),
2684                 t = parseInt(me.getStyle(TOP), 10);
2685         
2686         l = !isNaN(l) ? l : (relative ? 0 : me.dom.offsetLeft);
2687         t = !isNaN(t) ? t : (relative ? 0 : me.dom.offsetTop);        
2688
2689         return {left: (x - o[0] + l), top: (y - o[1] + t)}; 
2690     },
2691     
2692     animTest : function(args, animate, i) {
2693         return !!animate && this.preanim ? this.preanim(args, i) : false;
2694     }
2695 });
2696 })();
2697 Ext.Element.addMethods({
2698     
2699     isScrollable : function(){
2700         var dom = this.dom;
2701         return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
2702     },
2703
2704     
2705     scrollTo : function(side, value){
2706         this.dom["scroll" + (/top/i.test(side) ? "Top" : "Left")] = value;
2707         return this;
2708     },
2709
2710     
2711     getScroll : function(){
2712         var d = this.dom, 
2713             doc = document,
2714             body = doc.body,
2715             docElement = doc.documentElement,
2716             l,
2717             t,
2718             ret;
2719
2720         if(d == doc || d == body){
2721             if(Ext.isIE && Ext.isStrict){
2722                 l = docElement.scrollLeft; 
2723                 t = docElement.scrollTop;
2724             }else{
2725                 l = window.pageXOffset;
2726                 t = window.pageYOffset;
2727             }
2728             ret = {left: l || (body ? body.scrollLeft : 0), top: t || (body ? body.scrollTop : 0)};
2729         }else{
2730             ret = {left: d.scrollLeft, top: d.scrollTop};
2731         }
2732         return ret;
2733     }
2734 });
2735
2736 Ext.Element.VISIBILITY = 1;
2737
2738 Ext.Element.DISPLAY = 2;
2739
2740
2741 Ext.Element.OFFSETS = 3;
2742
2743
2744 Ext.Element.ASCLASS = 4;
2745
2746
2747 Ext.Element.visibilityCls = 'x-hide-nosize';
2748
2749 Ext.Element.addMethods(function(){
2750     var El = Ext.Element,
2751         OPACITY = "opacity",
2752         VISIBILITY = "visibility",
2753         DISPLAY = "display",
2754         HIDDEN = "hidden",
2755         OFFSETS = "offsets",
2756         ASCLASS = "asclass",
2757         NONE = "none",
2758         NOSIZE = 'nosize',
2759         ORIGINALDISPLAY = 'originalDisplay',
2760         VISMODE = 'visibilityMode',
2761         ISVISIBLE = 'isVisible',
2762         data = El.data,
2763         getDisplay = function(dom){
2764             var d = data(dom, ORIGINALDISPLAY);
2765             if(d === undefined){
2766                 data(dom, ORIGINALDISPLAY, d = '');
2767             }
2768             return d;
2769         },
2770         getVisMode = function(dom){
2771             var m = data(dom, VISMODE);
2772             if(m === undefined){
2773                 data(dom, VISMODE, m = 1);
2774             }
2775             return m;
2776         };
2777
2778     return {
2779         
2780         originalDisplay : "",
2781         visibilityMode : 1,
2782
2783         
2784         setVisibilityMode : function(visMode){
2785             data(this.dom, VISMODE, visMode);
2786             return this;
2787         },
2788
2789         
2790         animate : function(args, duration, onComplete, easing, animType){
2791             this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
2792             return this;
2793         },
2794
2795         
2796         anim : function(args, opt, animType, defaultDur, defaultEase, cb){
2797             animType = animType || 'run';
2798             opt = opt || {};
2799             var me = this,
2800                 anim = Ext.lib.Anim[animType](
2801                     me.dom,
2802                     args,
2803                     (opt.duration || defaultDur) || .35,
2804                     (opt.easing || defaultEase) || 'easeOut',
2805                     function(){
2806                         if(cb) cb.call(me);
2807                         if(opt.callback) opt.callback.call(opt.scope || me, me, opt);
2808                     },
2809                     me
2810                 );
2811             opt.anim = anim;
2812             return anim;
2813         },
2814
2815         
2816         preanim : function(a, i){
2817             return !a[i] ? false : (typeof a[i] == 'object' ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
2818         },
2819
2820         
2821         isVisible : function() {
2822             var me = this,
2823                 dom = me.dom,
2824                 visible = data(dom, ISVISIBLE);
2825
2826             if(typeof visible == 'boolean'){ 
2827                 return visible;
2828             }
2829             
2830             visible = !me.isStyle(VISIBILITY, HIDDEN) &&
2831                       !me.isStyle(DISPLAY, NONE) &&
2832                       !((getVisMode(dom) == El.ASCLASS) && me.hasClass(me.visibilityCls || El.visibilityCls));
2833
2834             data(dom, ISVISIBLE, visible);
2835             return visible;
2836         },
2837
2838         
2839         setVisible : function(visible, animate){
2840             var me = this, isDisplay, isVisibility, isOffsets, isNosize,
2841                 dom = me.dom,
2842                 visMode = getVisMode(dom);
2843
2844
2845             
2846             if (typeof animate == 'string'){
2847                 switch (animate) {
2848                     case DISPLAY:
2849                         visMode = El.DISPLAY;
2850                         break;
2851                     case VISIBILITY:
2852                         visMode = El.VISIBILITY;
2853                         break;
2854                     case OFFSETS:
2855                         visMode = El.OFFSETS;
2856                         break;
2857                     case NOSIZE:
2858                     case ASCLASS:
2859                         visMode = El.ASCLASS;
2860                         break;
2861                 }
2862                 me.setVisibilityMode(visMode);
2863                 animate = false;
2864             }
2865
2866             if (!animate || !me.anim) {
2867                 if(visMode == El.ASCLASS ){
2868
2869                     me[visible?'removeClass':'addClass'](me.visibilityCls || El.visibilityCls);
2870
2871                 } else if (visMode == El.DISPLAY){
2872
2873                     return me.setDisplayed(visible);
2874
2875                 } else if (visMode == El.OFFSETS){
2876
2877                     if (!visible){
2878                         me.hideModeStyles = {
2879                             position: me.getStyle('position'),
2880                             top: me.getStyle('top'),
2881                             left: me.getStyle('left')
2882                         };
2883                         me.applyStyles({position: 'absolute', top: '-10000px', left: '-10000px'});
2884                     } else {
2885                         me.applyStyles(me.hideModeStyles || {position: '', top: '', left: ''});
2886                         delete me.hideModeStyles;
2887                     }
2888
2889                 }else{
2890                     me.fixDisplay();
2891                     dom.style.visibility = visible ? "visible" : HIDDEN;
2892                 }
2893             }else{
2894                 
2895                 if(visible){
2896                     me.setOpacity(.01);
2897                     me.setVisible(true);
2898                 }
2899                 me.anim({opacity: { to: (visible?1:0) }},
2900                         me.preanim(arguments, 1),
2901                         null,
2902                         .35,
2903                         'easeIn',
2904                         function(){
2905                             visible || me.setVisible(false).setOpacity(1);
2906                         });
2907             }
2908             data(dom, ISVISIBLE, visible);  
2909             return me;
2910         },
2911
2912
2913         
2914         hasMetrics  : function(){
2915             var dom = this.dom;
2916             return this.isVisible() || (getVisMode(dom) == El.VISIBILITY);
2917         },
2918
2919         
2920         toggle : function(animate){
2921             var me = this;
2922             me.setVisible(!me.isVisible(), me.preanim(arguments, 0));
2923             return me;
2924         },
2925
2926         
2927         setDisplayed : function(value) {
2928             if(typeof value == "boolean"){
2929                value = value ? getDisplay(this.dom) : NONE;
2930             }
2931             this.setStyle(DISPLAY, value);
2932             return this;
2933         },
2934
2935         
2936         fixDisplay : function(){
2937             var me = this;
2938             if(me.isStyle(DISPLAY, NONE)){
2939                 me.setStyle(VISIBILITY, HIDDEN);
2940                 me.setStyle(DISPLAY, getDisplay(this.dom)); 
2941                 if(me.isStyle(DISPLAY, NONE)){ 
2942                     me.setStyle(DISPLAY, "block");
2943                 }
2944             }
2945         },
2946
2947         
2948         hide : function(animate){
2949             
2950             if (typeof animate == 'string'){
2951                 this.setVisible(false, animate);
2952                 return this;
2953             }
2954             this.setVisible(false, this.preanim(arguments, 0));
2955             return this;
2956         },
2957
2958         
2959         show : function(animate){
2960             
2961             if (typeof animate == 'string'){
2962                 this.setVisible(true, animate);
2963                 return this;
2964             }
2965             this.setVisible(true, this.preanim(arguments, 0));
2966             return this;
2967         }
2968     };
2969 }());(function(){
2970     
2971     var NULL = null,
2972         UNDEFINED = undefined,
2973         TRUE = true,
2974         FALSE = false,
2975         SETX = "setX",
2976         SETY = "setY",
2977         SETXY = "setXY",
2978         LEFT = "left",
2979         BOTTOM = "bottom",
2980         TOP = "top",
2981         RIGHT = "right",
2982         HEIGHT = "height",
2983         WIDTH = "width",
2984         POINTS = "points",
2985         HIDDEN = "hidden",
2986         ABSOLUTE = "absolute",
2987         VISIBLE = "visible",
2988         MOTION = "motion",
2989         POSITION = "position",
2990         EASEOUT = "easeOut",
2991         
2992         flyEl = new Ext.Element.Flyweight(),
2993         queues = {},
2994         getObject = function(o){
2995             return o || {};
2996         },
2997         fly = function(dom){
2998             flyEl.dom = dom;
2999             flyEl.id = Ext.id(dom);
3000             return flyEl;
3001         },
3002         
3003         getQueue = function(id){
3004             if(!queues[id]){
3005                 queues[id] = [];
3006             }
3007             return queues[id];
3008         },
3009         setQueue = function(id, value){
3010             queues[id] = value;
3011         };
3012         
3013
3014 Ext.enableFx = TRUE;
3015
3016
3017 Ext.Fx = {
3018     
3019     
3020     
3021     switchStatements : function(key, fn, argHash){
3022         return fn.apply(this, argHash[key]);
3023     },
3024     
3025     
3026     slideIn : function(anchor, o){ 
3027         o = getObject(o);
3028         var me = this,
3029             dom = me.dom,
3030             st = dom.style,
3031             xy,
3032             r,
3033             b,              
3034             wrap,               
3035             after,
3036             st,
3037             args, 
3038             pt,
3039             bw,
3040             bh;
3041             
3042         anchor = anchor || "t";
3043
3044         me.queueFx(o, function(){            
3045             xy = fly(dom).getXY();
3046             
3047             fly(dom).fixDisplay();            
3048             
3049             
3050             r = fly(dom).getFxRestore();      
3051             b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight};
3052             b.right = b.x + b.width;
3053             b.bottom = b.y + b.height;
3054             
3055             
3056             fly(dom).setWidth(b.width).setHeight(b.height);            
3057             
3058             
3059             wrap = fly(dom).fxWrap(r.pos, o, HIDDEN);
3060             
3061             st.visibility = VISIBLE;
3062             st.position = ABSOLUTE;
3063             
3064             
3065             function after(){
3066                  fly(dom).fxUnwrap(wrap, r.pos, o);
3067                  st.width = r.width;
3068                  st.height = r.height;
3069                  fly(dom).afterFx(o);
3070             }
3071             
3072             
3073             pt = {to: [b.x, b.y]}; 
3074             bw = {to: b.width};
3075             bh = {to: b.height};
3076                 
3077             function argCalc(wrap, style, ww, wh, sXY, sXYval, s1, s2, w, h, p){                    
3078                 var ret = {};
3079                 fly(wrap).setWidth(ww).setHeight(wh);
3080                 if(fly(wrap)[sXY]){
3081                     fly(wrap)[sXY](sXYval);                  
3082                 }
3083                 style[s1] = style[s2] = "0";                    
3084                 if(w){
3085                     ret.width = w;
3086                 }
3087                 if(h){
3088                     ret.height = h;
3089                 }
3090                 if(p){
3091                     ret.points = p;
3092                 }
3093                 return ret;
3094             };
3095
3096             args = fly(dom).switchStatements(anchor.toLowerCase(), argCalc, {
3097                     t  : [wrap, st, b.width, 0, NULL, NULL, LEFT, BOTTOM, NULL, bh, NULL],
3098                     l  : [wrap, st, 0, b.height, NULL, NULL, RIGHT, TOP, bw, NULL, NULL],
3099                     r  : [wrap, st, b.width, b.height, SETX, b.right, LEFT, TOP, NULL, NULL, pt],
3100                     b  : [wrap, st, b.width, b.height, SETY, b.bottom, LEFT, TOP, NULL, bh, pt],
3101                     tl : [wrap, st, 0, 0, NULL, NULL, RIGHT, BOTTOM, bw, bh, pt],
3102                     bl : [wrap, st, 0, 0, SETY, b.y + b.height, RIGHT, TOP, bw, bh, pt],
3103                     br : [wrap, st, 0, 0, SETXY, [b.right, b.bottom], LEFT, TOP, bw, bh, pt],
3104                     tr : [wrap, st, 0, 0, SETX, b.x + b.width, LEFT, BOTTOM, bw, bh, pt]
3105                 });
3106             
3107             st.visibility = VISIBLE;
3108             fly(wrap).show();
3109
3110             arguments.callee.anim = fly(wrap).fxanim(args,
3111                 o,
3112                 MOTION,
3113                 .5,
3114                 EASEOUT, 
3115                 after);
3116         });
3117         return me;
3118     },
3119     
3120     
3121     slideOut : function(anchor, o){
3122         o = getObject(o);
3123         var me = this,
3124             dom = me.dom,
3125             st = dom.style,
3126             xy = me.getXY(),
3127             wrap,
3128             r,
3129             b,
3130             a,
3131             zero = {to: 0}; 
3132                     
3133         anchor = anchor || "t";
3134
3135         me.queueFx(o, function(){
3136             
3137             
3138             r = fly(dom).getFxRestore(); 
3139             b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight};
3140             b.right = b.x + b.width;
3141             b.bottom = b.y + b.height;
3142                 
3143             
3144             fly(dom).setWidth(b.width).setHeight(b.height);
3145
3146             
3147             wrap = fly(dom).fxWrap(r.pos, o, VISIBLE);
3148                 
3149             st.visibility = VISIBLE;
3150             st.position = ABSOLUTE;
3151             fly(wrap).setWidth(b.width).setHeight(b.height);            
3152
3153             function after(){
3154                 o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();                
3155                 fly(dom).fxUnwrap(wrap, r.pos, o);
3156                 st.width = r.width;
3157                 st.height = r.height;
3158                 fly(dom).afterFx(o);
3159             }            
3160             
3161             function argCalc(style, s1, s2, p1, v1, p2, v2, p3, v3){                    
3162                 var ret = {};
3163                 
3164                 style[s1] = style[s2] = "0";
3165                 ret[p1] = v1;               
3166                 if(p2){
3167                     ret[p2] = v2;               
3168                 }
3169                 if(p3){
3170                     ret[p3] = v3;
3171                 }
3172                 
3173                 return ret;
3174             };
3175             
3176             a = fly(dom).switchStatements(anchor.toLowerCase(), argCalc, {
3177                 t  : [st, LEFT, BOTTOM, HEIGHT, zero],
3178                 l  : [st, RIGHT, TOP, WIDTH, zero],
3179                 r  : [st, LEFT, TOP, WIDTH, zero, POINTS, {to : [b.right, b.y]}],
3180                 b  : [st, LEFT, TOP, HEIGHT, zero, POINTS, {to : [b.x, b.bottom]}],
3181                 tl : [st, RIGHT, BOTTOM, WIDTH, zero, HEIGHT, zero],
3182                 bl : [st, RIGHT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.x, b.bottom]}],
3183                 br : [st, LEFT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.x + b.width, b.bottom]}],
3184                 tr : [st, LEFT, BOTTOM, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.right, b.y]}]
3185             });
3186             
3187             arguments.callee.anim = fly(wrap).fxanim(a,
3188                 o,
3189                 MOTION,
3190                 .5,
3191                 EASEOUT, 
3192                 after);
3193         });
3194         return me;
3195     },
3196
3197     
3198     puff : function(o){
3199         o = getObject(o);
3200         var me = this,
3201             dom = me.dom,
3202             st = dom.style,
3203             width,
3204             height,
3205             r;
3206
3207         me.queueFx(o, function(){
3208             width = fly(dom).getWidth();
3209             height = fly(dom).getHeight();
3210             fly(dom).clearOpacity();
3211             fly(dom).show();
3212
3213             
3214             r = fly(dom).getFxRestore();                   
3215             
3216             function after(){
3217                 o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();                  
3218                 fly(dom).clearOpacity();  
3219                 fly(dom).setPositioning(r.pos);
3220                 st.width = r.width;
3221                 st.height = r.height;
3222                 st.fontSize = '';
3223                 fly(dom).afterFx(o);
3224             }   
3225
3226             arguments.callee.anim = fly(dom).fxanim({
3227                     width : {to : fly(dom).adjustWidth(width * 2)},
3228                     height : {to : fly(dom).adjustHeight(height * 2)},
3229                     points : {by : [-width * .5, -height * .5]},
3230                     opacity : {to : 0},
3231                     fontSize: {to : 200, unit: "%"}
3232                 },
3233                 o,
3234                 MOTION,
3235                 .5,
3236                 EASEOUT,
3237                  after);
3238         });
3239         return me;
3240     },
3241
3242     
3243     switchOff : function(o){
3244         o = getObject(o);
3245         var me = this,
3246             dom = me.dom,
3247             st = dom.style,
3248             r;
3249
3250         me.queueFx(o, function(){
3251             fly(dom).clearOpacity();
3252             fly(dom).clip();
3253
3254             
3255             r = fly(dom).getFxRestore();
3256                 
3257             function after(){
3258                 o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();  
3259                 fly(dom).clearOpacity();
3260                 fly(dom).setPositioning(r.pos);
3261                 st.width = r.width;
3262                 st.height = r.height;   
3263                 fly(dom).afterFx(o);
3264             };
3265
3266             fly(dom).fxanim({opacity : {to : 0.3}}, 
3267                 NULL, 
3268                 NULL, 
3269                 .1, 
3270                 NULL, 
3271                 function(){                                 
3272                     fly(dom).clearOpacity();
3273                         (function(){                            
3274                             fly(dom).fxanim({
3275                                 height : {to : 1},
3276                                 points : {by : [0, fly(dom).getHeight() * .5]}
3277                             }, 
3278                             o, 
3279                             MOTION, 
3280                             0.3, 
3281                             'easeIn', 
3282                             after);
3283                         }).defer(100);
3284                 });
3285         });
3286         return me;
3287     },
3288
3289      
3290     highlight : function(color, o){
3291         o = getObject(o);
3292         var me = this,
3293             dom = me.dom,
3294             attr = o.attr || "backgroundColor",
3295             a = {},
3296             restore;
3297
3298         me.queueFx(o, function(){
3299             fly(dom).clearOpacity();
3300             fly(dom).show();
3301
3302             function after(){
3303                 dom.style[attr] = restore;
3304                 fly(dom).afterFx(o);
3305             }            
3306             restore = dom.style[attr];
3307             a[attr] = {from: color || "ffff9c", to: o.endColor || fly(dom).getColor(attr) || "ffffff"};
3308             arguments.callee.anim = fly(dom).fxanim(a,
3309                 o,
3310                 'color',
3311                 1,
3312                 'easeIn', 
3313                 after);
3314         });
3315         return me;
3316     },
3317
3318    
3319     frame : function(color, count, o){
3320         o = getObject(o);
3321         var me = this,
3322             dom = me.dom,
3323             proxy,
3324             active;
3325
3326         me.queueFx(o, function(){
3327             color = color || '#C3DAF9';
3328             if(color.length == 6){
3329                 color = '#' + color;
3330             }            
3331             count = count || 1;
3332             fly(dom).show();
3333
3334             var xy = fly(dom).getXY(),
3335                 b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight},
3336                 queue = function(){
3337                     proxy = fly(document.body || document.documentElement).createChild({
3338                         style:{
3339                             position : ABSOLUTE,
3340                             'z-index': 35000, 
3341                             border : '0px solid ' + color
3342                         }
3343                     });
3344                     return proxy.queueFx({}, animFn);
3345                 };
3346             
3347             
3348             arguments.callee.anim = {
3349                 isAnimated: true,
3350                 stop: function() {
3351                     count = 0;
3352                     proxy.stopFx();
3353                 }
3354             };
3355             
3356             function animFn(){
3357                 var scale = Ext.isBorderBox ? 2 : 1;
3358                 active = proxy.anim({
3359                     top : {from : b.y, to : b.y - 20},
3360                     left : {from : b.x, to : b.x - 20},
3361                     borderWidth : {from : 0, to : 10},
3362                     opacity : {from : 1, to : 0},
3363                     height : {from : b.height, to : b.height + 20 * scale},
3364                     width : {from : b.width, to : b.width + 20 * scale}
3365                 },{
3366                     duration: o.duration || 1,
3367                     callback: function() {
3368                         proxy.remove();
3369                         --count > 0 ? queue() : fly(dom).afterFx(o);
3370                     }
3371                 });
3372                 arguments.callee.anim = {
3373                     isAnimated: true,
3374                     stop: function(){
3375                         active.stop();
3376                     }
3377                 };
3378             };
3379             queue();
3380         });
3381         return me;
3382     },
3383
3384    
3385     pause : function(seconds){        
3386         var dom = this.dom,
3387             t;
3388
3389         this.queueFx({}, function(){
3390             t = setTimeout(function(){
3391                 fly(dom).afterFx({});
3392             }, seconds * 1000);
3393             arguments.callee.anim = {
3394                 isAnimated: true,
3395                 stop: function(){
3396                     clearTimeout(t);
3397                     fly(dom).afterFx({});
3398                 }
3399             };
3400         });
3401         return this;
3402     },
3403
3404    
3405     fadeIn : function(o){
3406         o = getObject(o);
3407         var me = this,
3408             dom = me.dom,
3409             to = o.endOpacity || 1;
3410         
3411         me.queueFx(o, function(){
3412             fly(dom).setOpacity(0);
3413             fly(dom).fixDisplay();
3414             dom.style.visibility = VISIBLE;
3415             arguments.callee.anim = fly(dom).fxanim({opacity:{to:to}},
3416                 o, NULL, .5, EASEOUT, function(){
3417                 if(to == 1){
3418                     fly(dom).clearOpacity();
3419                 }
3420                 fly(dom).afterFx(o);
3421             });
3422         });
3423         return me;
3424     },
3425
3426    
3427     fadeOut : function(o){
3428         o = getObject(o);
3429         var me = this,
3430             dom = me.dom,
3431             style = dom.style,
3432             to = o.endOpacity || 0;         
3433         
3434         me.queueFx(o, function(){  
3435             arguments.callee.anim = fly(dom).fxanim({ 
3436                 opacity : {to : to}},
3437                 o, 
3438                 NULL, 
3439                 .5, 
3440                 EASEOUT, 
3441                 function(){
3442                     if(to == 0){
3443                         Ext.Element.data(dom, 'visibilityMode') == Ext.Element.DISPLAY || o.useDisplay ? 
3444                             style.display = "none" :
3445                             style.visibility = HIDDEN;
3446                             
3447                         fly(dom).clearOpacity();
3448                     }
3449                     fly(dom).afterFx(o);
3450             });
3451         });
3452         return me;
3453     },
3454
3455    
3456     scale : function(w, h, o){
3457         this.shift(Ext.apply({}, o, {
3458             width: w,
3459             height: h
3460         }));
3461         return this;
3462     },
3463
3464    
3465     shift : function(o){
3466         o = getObject(o);
3467         var dom = this.dom,
3468             a = {};
3469                 
3470         this.queueFx(o, function(){
3471             for (var prop in o) {
3472                 if (o[prop] != UNDEFINED) {                                                 
3473                     a[prop] = {to : o[prop]};                   
3474                 }
3475             } 
3476             
3477             a.width ? a.width.to = fly(dom).adjustWidth(o.width) : a;
3478             a.height ? a.height.to = fly(dom).adjustWidth(o.height) : a;   
3479             
3480             if (a.x || a.y || a.xy) {
3481                 a.points = a.xy || 
3482                            {to : [ a.x ? a.x.to : fly(dom).getX(),
3483                                    a.y ? a.y.to : fly(dom).getY()]};                  
3484             }
3485
3486             arguments.callee.anim = fly(dom).fxanim(a,
3487                 o, 
3488                 MOTION, 
3489                 .35, 
3490                 EASEOUT, 
3491                 function(){
3492                     fly(dom).afterFx(o);
3493                 });
3494         });
3495         return this;
3496     },
3497
3498     
3499     ghost : function(anchor, o){
3500         o = getObject(o);
3501         var me = this,
3502             dom = me.dom,
3503             st = dom.style,
3504             a = {opacity: {to: 0}, points: {}},
3505             pt = a.points,
3506             r,
3507             w,
3508             h;
3509             
3510         anchor = anchor || "b";
3511
3512         me.queueFx(o, function(){
3513             
3514             r = fly(dom).getFxRestore();
3515             w = fly(dom).getWidth();
3516             h = fly(dom).getHeight();
3517             
3518             function after(){
3519                 o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();   
3520                 fly(dom).clearOpacity();
3521                 fly(dom).setPositioning(r.pos);
3522                 st.width = r.width;
3523                 st.height = r.height;
3524                 fly(dom).afterFx(o);
3525             }
3526                 
3527             pt.by = fly(dom).switchStatements(anchor.toLowerCase(), function(v1,v2){ return [v1, v2];}, {
3528                t  : [0, -h],
3529                l  : [-w, 0],
3530                r  : [w, 0],
3531                b  : [0, h],
3532                tl : [-w, -h],
3533                bl : [-w, h],
3534                br : [w, h],
3535                tr : [w, -h] 
3536             });
3537                 
3538             arguments.callee.anim = fly(dom).fxanim(a,
3539                 o,
3540                 MOTION,
3541                 .5,
3542                 EASEOUT, after);
3543         });
3544         return me;
3545     },
3546
3547     
3548     syncFx : function(){
3549         var me = this;
3550         me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
3551             block : FALSE,
3552             concurrent : TRUE,
3553             stopFx : FALSE
3554         });
3555         return me;
3556     },
3557
3558     
3559     sequenceFx : function(){
3560         var me = this;
3561         me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
3562             block : FALSE,
3563             concurrent : FALSE,
3564             stopFx : FALSE
3565         });
3566         return me;
3567     },
3568
3569     
3570     nextFx : function(){        
3571         var ef = getQueue(this.dom.id)[0];
3572         if(ef){
3573             ef.call(this);
3574         }
3575     },
3576
3577     
3578     hasActiveFx : function(){
3579         return getQueue(this.dom.id)[0];
3580     },
3581
3582     
3583     stopFx : function(finish){
3584         var me = this,
3585             id = me.dom.id;
3586         if(me.hasActiveFx()){
3587             var cur = getQueue(id)[0];
3588             if(cur && cur.anim){
3589                 if(cur.anim.isAnimated){
3590                     setQueue(id, [cur]); 
3591                     cur.anim.stop(finish !== undefined ? finish : TRUE);
3592                 }else{
3593                     setQueue(id, []);
3594                 }
3595             }
3596         }
3597         return me;
3598     },
3599
3600     
3601     beforeFx : function(o){
3602         if(this.hasActiveFx() && !o.concurrent){
3603            if(o.stopFx){
3604                this.stopFx();
3605                return TRUE;
3606            }
3607            return FALSE;
3608         }
3609         return TRUE;
3610     },
3611
3612     
3613     hasFxBlock : function(){
3614         var q = getQueue(this.dom.id);
3615         return q && q[0] && q[0].block;
3616     },
3617
3618     
3619     queueFx : function(o, fn){
3620         var me = fly(this.dom);
3621         if(!me.hasFxBlock()){
3622             Ext.applyIf(o, me.fxDefaults);
3623             if(!o.concurrent){
3624                 var run = me.beforeFx(o);
3625                 fn.block = o.block;
3626                 getQueue(me.dom.id).push(fn);
3627                 if(run){
3628                     me.nextFx();
3629                 }
3630             }else{
3631                 fn.call(me);
3632             }
3633         }
3634         return me;
3635     },
3636
3637     
3638     fxWrap : function(pos, o, vis){ 
3639         var dom = this.dom,
3640             wrap,
3641             wrapXY;
3642         if(!o.wrap || !(wrap = Ext.getDom(o.wrap))){            
3643             if(o.fixPosition){
3644                 wrapXY = fly(dom).getXY();
3645             }
3646             var div = document.createElement("div");
3647             div.style.visibility = vis;
3648             wrap = dom.parentNode.insertBefore(div, dom);
3649             fly(wrap).setPositioning(pos);
3650             if(fly(wrap).isStyle(POSITION, "static")){
3651                 fly(wrap).position("relative");
3652             }
3653             fly(dom).clearPositioning('auto');
3654             fly(wrap).clip();
3655             wrap.appendChild(dom);
3656             if(wrapXY){
3657                 fly(wrap).setXY(wrapXY);
3658             }
3659         }
3660         return wrap;
3661     },
3662
3663     
3664     fxUnwrap : function(wrap, pos, o){      
3665         var dom = this.dom;
3666         fly(dom).clearPositioning();
3667         fly(dom).setPositioning(pos);
3668         if(!o.wrap){
3669             var pn = fly(wrap).dom.parentNode;
3670             pn.insertBefore(dom, wrap); 
3671             fly(wrap).remove();
3672         }
3673     },
3674
3675     
3676     getFxRestore : function(){
3677         var st = this.dom.style;
3678         return {pos: this.getPositioning(), width: st.width, height : st.height};
3679     },
3680
3681     
3682     afterFx : function(o){
3683         var dom = this.dom,
3684             id = dom.id;
3685         if(o.afterStyle){
3686             fly(dom).setStyle(o.afterStyle);            
3687         }
3688         if(o.afterCls){
3689             fly(dom).addClass(o.afterCls);
3690         }
3691         if(o.remove == TRUE){
3692             fly(dom).remove();
3693         }
3694         if(o.callback){
3695             o.callback.call(o.scope, fly(dom));
3696         }
3697         if(!o.concurrent){
3698             getQueue(id).shift();
3699             fly(dom).nextFx();
3700         }
3701     },
3702
3703     
3704     fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
3705         animType = animType || 'run';
3706         opt = opt || {};
3707         var anim = Ext.lib.Anim[animType](
3708                 this.dom, 
3709                 args,
3710                 (opt.duration || defaultDur) || .35,
3711                 (opt.easing || defaultEase) || EASEOUT,
3712                 cb,            
3713                 this
3714             );
3715         opt.anim = anim;
3716         return anim;
3717     }
3718 };
3719
3720
3721 Ext.Fx.resize = Ext.Fx.scale;
3722
3723
3724
3725 Ext.Element.addMethods(Ext.Fx);
3726 })();
3727
3728 Ext.CompositeElementLite = function(els, root){
3729     
3730     this.elements = [];
3731     this.add(els, root);
3732     this.el = new Ext.Element.Flyweight();
3733 };
3734
3735 Ext.CompositeElementLite.prototype = {
3736     isComposite: true,
3737
3738     
3739     getElement : function(el){
3740         
3741         var e = this.el;
3742         e.dom = el;
3743         e.id = el.id;
3744         return e;
3745     },
3746
3747     
3748     transformElement : function(el){
3749         return Ext.getDom(el);
3750     },
3751
3752     
3753     getCount : function(){
3754         return this.elements.length;
3755     },
3756     
3757     add : function(els, root){
3758         var me = this,
3759             elements = me.elements;
3760         if(!els){
3761             return this;
3762         }
3763         if(typeof els == "string"){
3764             els = Ext.Element.selectorFunction(els, root);
3765         }else if(els.isComposite){
3766             els = els.elements;
3767         }else if(!Ext.isIterable(els)){
3768             els = [els];
3769         }
3770
3771         for(var i = 0, len = els.length; i < len; ++i){
3772             elements.push(me.transformElement(els[i]));
3773         }
3774         return me;
3775     },
3776
3777     invoke : function(fn, args){
3778         var me = this,
3779             els = me.elements,
3780             len = els.length,
3781             e,
3782             i;
3783
3784         for(i = 0; i < len; i++) {
3785             e = els[i];
3786             if(e){
3787                 Ext.Element.prototype[fn].apply(me.getElement(e), args);
3788             }
3789         }
3790         return me;
3791     },
3792     
3793     item : function(index){
3794         var me = this,
3795             el = me.elements[index],
3796             out = null;
3797
3798         if(el){
3799             out = me.getElement(el);
3800         }
3801         return out;
3802     },
3803
3804     
3805     addListener : function(eventName, handler, scope, opt){
3806         var els = this.elements,
3807             len = els.length,
3808             i, e;
3809
3810         for(i = 0; i<len; i++) {
3811             e = els[i];
3812             if(e) {
3813                 Ext.EventManager.on(e, eventName, handler, scope || e, opt);
3814             }
3815         }
3816         return this;
3817     },
3818     
3819     each : function(fn, scope){
3820         var me = this,
3821             els = me.elements,
3822             len = els.length,
3823             i, e;
3824
3825         for(i = 0; i<len; i++) {
3826             e = els[i];
3827             if(e){
3828                 e = this.getElement(e);
3829                 if(fn.call(scope || e, e, me, i) === false){
3830                     break;
3831                 }
3832             }
3833         }
3834         return me;
3835     },
3836
3837     
3838     fill : function(els){
3839         var me = this;
3840         me.elements = [];
3841         me.add(els);
3842         return me;
3843     },
3844
3845     
3846     filter : function(selector){
3847         var els = [],
3848             me = this,
3849             fn = Ext.isFunction(selector) ? selector
3850                 : function(el){
3851                     return el.is(selector);
3852                 };
3853
3854         me.each(function(el, self, i) {
3855             if (fn(el, i) !== false) {
3856                 els[els.length] = me.transformElement(el);
3857             }
3858         });
3859         
3860         me.elements = els;
3861         return me;
3862     },
3863
3864     
3865     indexOf : function(el){
3866         return this.elements.indexOf(this.transformElement(el));
3867     },
3868
3869     
3870     replaceElement : function(el, replacement, domReplace){
3871         var index = !isNaN(el) ? el : this.indexOf(el),
3872             d;
3873         if(index > -1){
3874             replacement = Ext.getDom(replacement);
3875             if(domReplace){
3876                 d = this.elements[index];
3877                 d.parentNode.insertBefore(replacement, d);
3878                 Ext.removeNode(d);
3879             }
3880             this.elements.splice(index, 1, replacement);
3881         }
3882         return this;
3883     },
3884
3885     
3886     clear : function(){
3887         this.elements = [];
3888     }
3889 };
3890
3891 Ext.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;
3892
3893
3894 Ext.CompositeElementLite.importElementMethods = function() {
3895     var fnName,
3896         ElProto = Ext.Element.prototype,
3897         CelProto = Ext.CompositeElementLite.prototype;
3898
3899     for (fnName in ElProto) {
3900         if (typeof ElProto[fnName] == 'function'){
3901             (function(fnName) {
3902                 CelProto[fnName] = CelProto[fnName] || function() {
3903                     return this.invoke(fnName, arguments);
3904                 };
3905             }).call(CelProto, fnName);
3906
3907         }
3908     }
3909 };
3910
3911 Ext.CompositeElementLite.importElementMethods();
3912
3913 if(Ext.DomQuery){
3914     Ext.Element.selectorFunction = Ext.DomQuery.select;
3915 }
3916
3917
3918 Ext.Element.select = function(selector, root){
3919     var els;
3920     if(typeof selector == "string"){
3921         els = Ext.Element.selectorFunction(selector, root);
3922     }else if(selector.length !== undefined){
3923         els = selector;
3924     }else{
3925         throw "Invalid selector";
3926     }
3927     return new Ext.CompositeElementLite(els);
3928 };
3929
3930 Ext.select = Ext.Element.select;
3931 (function(){
3932     var BEFOREREQUEST = "beforerequest",
3933         REQUESTCOMPLETE = "requestcomplete",
3934         REQUESTEXCEPTION = "requestexception",
3935         UNDEFINED = undefined,
3936         LOAD = 'load',
3937         POST = 'POST',
3938         GET = 'GET',
3939         WINDOW = window;
3940
3941     
3942     Ext.data.Connection = function(config){
3943         Ext.apply(this, config);
3944         this.addEvents(
3945             
3946             BEFOREREQUEST,
3947             
3948             REQUESTCOMPLETE,
3949             
3950             REQUESTEXCEPTION
3951         );
3952         Ext.data.Connection.superclass.constructor.call(this);
3953     };
3954
3955     Ext.extend(Ext.data.Connection, Ext.util.Observable, {
3956         
3957         
3958         
3959         
3960         
3961         timeout : 30000,
3962         
3963         autoAbort:false,
3964
3965         
3966         disableCaching: true,
3967
3968         
3969         disableCachingParam: '_dc',
3970
3971         
3972         request : function(o){
3973             var me = this;
3974             if(me.fireEvent(BEFOREREQUEST, me, o)){
3975                 if (o.el) {
3976                     if(!Ext.isEmpty(o.indicatorText)){
3977                         me.indicatorText = '<div class="loading-indicator">'+o.indicatorText+"</div>";
3978                     }
3979                     if(me.indicatorText) {
3980                         Ext.getDom(o.el).innerHTML = me.indicatorText;
3981                     }
3982                     o.success = (Ext.isFunction(o.success) ? o.success : function(){}).createInterceptor(function(response) {
3983                         Ext.getDom(o.el).innerHTML = response.responseText;
3984                     });
3985                 }
3986
3987                 var p = o.params,
3988                     url = o.url || me.url,
3989                     method,
3990                     cb = {success: me.handleResponse,
3991                           failure: me.handleFailure,
3992                           scope: me,
3993                           argument: {options: o},
3994                           timeout : Ext.num(o.timeout, me.timeout)
3995                     },
3996                     form,
3997                     serForm;
3998
3999
4000                 if (Ext.isFunction(p)) {
4001                     p = p.call(o.scope||WINDOW, o);
4002                 }
4003
4004                 p = Ext.urlEncode(me.extraParams, Ext.isObject(p) ? Ext.urlEncode(p) : p);
4005
4006                 if (Ext.isFunction(url)) {
4007                     url = url.call(o.scope || WINDOW, o);
4008                 }
4009
4010                 if((form = Ext.getDom(o.form))){
4011                     url = url || form.action;
4012                      if(o.isUpload || (/multipart\/form-data/i.test(form.getAttribute("enctype")))) {
4013                          return me.doFormUpload.call(me, o, p, url);
4014                      }
4015                     serForm = Ext.lib.Ajax.serializeForm(form);
4016                     p = p ? (p + '&' + serForm) : serForm;
4017                 }
4018
4019                 method = o.method || me.method || ((p || o.xmlData || o.jsonData) ? POST : GET);
4020
4021                 if(method === GET && (me.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
4022                     var dcp = o.disableCachingParam || me.disableCachingParam;
4023                     url = Ext.urlAppend(url, dcp + '=' + (new Date().getTime()));
4024                 }
4025
4026                 o.headers = Ext.apply(o.headers || {}, me.defaultHeaders || {});
4027
4028                 if(o.autoAbort === true || me.autoAbort) {
4029                     me.abort();
4030                 }
4031
4032                 if((method == GET || o.xmlData || o.jsonData) && p){
4033                     url = Ext.urlAppend(url, p);
4034                     p = '';
4035                 }
4036                 return (me.transId = Ext.lib.Ajax.request(method, url, cb, p, o));
4037             }else{
4038                 return o.callback ? o.callback.apply(o.scope, [o,UNDEFINED,UNDEFINED]) : null;
4039             }
4040         },
4041
4042         
4043         isLoading : function(transId){
4044             return transId ? Ext.lib.Ajax.isCallInProgress(transId) : !! this.transId;
4045         },
4046
4047         
4048         abort : function(transId){
4049             if(transId || this.isLoading()){
4050                 Ext.lib.Ajax.abort(transId || this.transId);
4051             }
4052         },
4053
4054         
4055         handleResponse : function(response){
4056             this.transId = false;
4057             var options = response.argument.options;
4058             response.argument = options ? options.argument : null;
4059             this.fireEvent(REQUESTCOMPLETE, this, response, options);
4060             if(options.success){
4061                 options.success.call(options.scope, response, options);
4062             }
4063             if(options.callback){
4064                 options.callback.call(options.scope, options, true, response);
4065             }
4066         },
4067
4068         
4069         handleFailure : function(response, e){
4070             this.transId = false;
4071             var options = response.argument.options;
4072             response.argument = options ? options.argument : null;
4073             this.fireEvent(REQUESTEXCEPTION, this, response, options, e);
4074             if(options.failure){
4075                 options.failure.call(options.scope, response, options);
4076             }
4077             if(options.callback){
4078                 options.callback.call(options.scope, options, false, response);
4079             }
4080         },
4081
4082         
4083         doFormUpload : function(o, ps, url){
4084             var id = Ext.id(),
4085                 doc = document,
4086                 frame = doc.createElement('iframe'),
4087                 form = Ext.getDom(o.form),
4088                 hiddens = [],
4089                 hd,
4090                 encoding = 'multipart/form-data',
4091                 buf = {
4092                     target: form.target,
4093                     method: form.method,
4094                     encoding: form.encoding,
4095                     enctype: form.enctype,
4096                     action: form.action
4097                 };
4098
4099             
4100             Ext.fly(frame).set({
4101                 id: id,
4102                 name: id,
4103                 cls: 'x-hidden',
4104                 src: Ext.SSL_SECURE_URL
4105             }); 
4106
4107             doc.body.appendChild(frame);
4108
4109             
4110             if(Ext.isIE){
4111                document.frames[id].name = id;
4112             }
4113
4114
4115             Ext.fly(form).set({
4116                 target: id,
4117                 method: POST,
4118                 enctype: encoding,
4119                 encoding: encoding,
4120                 action: url || buf.action
4121             });
4122
4123             
4124             Ext.iterate(Ext.urlDecode(ps, false), function(k, v){
4125                 hd = doc.createElement('input');
4126                 Ext.fly(hd).set({
4127                     type: 'hidden',
4128                     value: v,
4129                     name: k
4130                 });
4131                 form.appendChild(hd);
4132                 hiddens.push(hd);
4133             });
4134
4135             function cb(){
4136                 var me = this,
4137                     
4138                     r = {responseText : '',
4139                          responseXML : null,
4140                          argument : o.argument},
4141                     doc,
4142                     firstChild;
4143
4144                 try{
4145                     doc = frame.contentWindow.document || frame.contentDocument || WINDOW.frames[id].document;
4146                     if(doc){
4147                         if(doc.body){
4148                             if(/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName)){ 
4149                                 r.responseText = firstChild.value;
4150                             }else{
4151                                 r.responseText = doc.body.innerHTML;
4152                             }
4153                         }
4154                         
4155                         r.responseXML = doc.XMLDocument || doc;
4156                     }
4157                 }
4158                 catch(e) {}
4159
4160                 Ext.EventManager.removeListener(frame, LOAD, cb, me);
4161
4162                 me.fireEvent(REQUESTCOMPLETE, me, r, o);
4163
4164                 function runCallback(fn, scope, args){
4165                     if(Ext.isFunction(fn)){
4166                         fn.apply(scope, args);
4167                     }
4168                 }
4169
4170                 runCallback(o.success, o.scope, [r, o]);
4171                 runCallback(o.callback, o.scope, [o, true, r]);
4172
4173                 if(!me.debugUploads){
4174                     setTimeout(function(){Ext.removeNode(frame);}, 100);
4175                 }
4176             }
4177
4178             Ext.EventManager.on(frame, LOAD, cb, this);
4179             form.submit();
4180
4181             Ext.fly(form).set(buf);
4182             Ext.each(hiddens, function(h) {
4183                 Ext.removeNode(h);
4184             });
4185         }
4186     });
4187 })();
4188
4189
4190 Ext.Ajax = new Ext.data.Connection({
4191     
4192     
4193     
4194     
4195     
4196     
4197
4198     
4199
4200     
4201     
4202     
4203     
4204     
4205     
4206
4207     
4208     autoAbort : false,
4209
4210     
4211     serializeForm : function(form){
4212         return Ext.lib.Ajax.serializeForm(form);
4213     }
4214 });
4215
4216 Ext.util.JSON = new (function(){
4217     var useHasOwn = !!{}.hasOwnProperty,
4218         isNative = function() {
4219             var useNative = null;
4220
4221             return function() {
4222                 if (useNative === null) {
4223                     useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]';
4224                 }
4225         
4226                 return useNative;
4227             };
4228         }(),
4229         pad = function(n) {
4230             return n < 10 ? "0" + n : n;
4231         },
4232         doDecode = function(json){
4233             return eval("(" + json + ")");    
4234         },
4235         doEncode = function(o){
4236             if(!Ext.isDefined(o) || o === null){
4237                 return "null";
4238             }else if(Ext.isArray(o)){
4239                 return encodeArray(o);
4240             }else if(Ext.isDate(o)){
4241                 return Ext.util.JSON.encodeDate(o);
4242             }else if(Ext.isString(o)){
4243                 return encodeString(o);
4244             }else if(typeof o == "number"){
4245                 
4246                 return isFinite(o) ? String(o) : "null";
4247             }else if(Ext.isBoolean(o)){
4248                 return String(o);
4249             }else {
4250                 var a = ["{"], b, i, v;
4251                 for (i in o) {
4252                     
4253                     if(!o.getElementsByTagName){
4254                         if(!useHasOwn || o.hasOwnProperty(i)) {
4255                             v = o[i];
4256                             switch (typeof v) {
4257                             case "undefined":
4258                             case "function":
4259                             case "unknown":
4260                                 break;
4261                             default:
4262                                 if(b){
4263                                     a.push(',');
4264                                 }
4265                                 a.push(doEncode(i), ":",
4266                                         v === null ? "null" : doEncode(v));
4267                                 b = true;
4268                             }
4269                         }
4270                     }
4271                 }
4272                 a.push("}");
4273                 return a.join("");
4274             }    
4275         },
4276         m = {
4277             "\b": '\\b',
4278             "\t": '\\t',
4279             "\n": '\\n',
4280             "\f": '\\f',
4281             "\r": '\\r',
4282             '"' : '\\"',
4283             "\\": '\\\\'
4284         },
4285         encodeString = function(s){
4286             if (/["\\\x00-\x1f]/.test(s)) {
4287                 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
4288                     var c = m[b];
4289                     if(c){
4290                         return c;
4291                     }
4292                     c = b.charCodeAt();
4293                     return "\\u00" +
4294                         Math.floor(c / 16).toString(16) +
4295                         (c % 16).toString(16);
4296                 }) + '"';
4297             }
4298             return '"' + s + '"';
4299         },
4300         encodeArray = function(o){
4301             var a = ["["], b, i, l = o.length, v;
4302                 for (i = 0; i < l; i += 1) {
4303                     v = o[i];
4304                     switch (typeof v) {
4305                         case "undefined":
4306                         case "function":
4307                         case "unknown":
4308                             break;
4309                         default:
4310                             if (b) {
4311                                 a.push(',');
4312                             }
4313                             a.push(v === null ? "null" : Ext.util.JSON.encode(v));
4314                             b = true;
4315                     }
4316                 }
4317                 a.push("]");
4318                 return a.join("");
4319         };
4320
4321     
4322     this.encodeDate = function(o){
4323         return '"' + o.getFullYear() + "-" +
4324                 pad(o.getMonth() + 1) + "-" +
4325                 pad(o.getDate()) + "T" +
4326                 pad(o.getHours()) + ":" +
4327                 pad(o.getMinutes()) + ":" +
4328                 pad(o.getSeconds()) + '"';
4329     };
4330
4331     
4332     this.encode = function() {
4333         var ec;
4334         return function(o) {
4335             if (!ec) {
4336                 
4337                 ec = isNative() ? JSON.stringify : doEncode;
4338             }
4339             return ec(o);
4340         };
4341     }();
4342
4343
4344     
4345     this.decode = function() {
4346         var dc;
4347         return function(json) {
4348             if (!dc) {
4349                 
4350                 dc = isNative() ? JSON.parse : doDecode;
4351             }
4352             return dc(json);
4353         };
4354     }();
4355
4356 })();
4357
4358 Ext.encode = Ext.util.JSON.encode;
4359
4360 Ext.decode = Ext.util.JSON.decode;
4361
4362 Ext.EventManager = function(){
4363     var docReadyEvent,
4364         docReadyProcId,
4365         docReadyState = false,
4366         DETECT_NATIVE = Ext.isGecko || Ext.isWebKit || Ext.isSafari,
4367         E = Ext.lib.Event,
4368         D = Ext.lib.Dom,
4369         DOC = document,
4370         WINDOW = window,
4371         DOMCONTENTLOADED = "DOMContentLoaded",
4372         COMPLETE = 'complete',
4373         propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
4374         
4375         specialElCache = [];
4376
4377      function getId(el){
4378         var id = false,
4379             i = 0,
4380             len = specialElCache.length,
4381             skip = false,
4382             o;
4383             
4384         if (el) {
4385             if (el.getElementById || el.navigator) {
4386                 
4387                 for(; i < len; ++i){
4388                     o = specialElCache[i];
4389                     if(o.el === el){
4390                         id = o.id;
4391                         break;
4392                     }
4393                 }
4394                 if(!id){
4395                     
4396                     id = Ext.id(el);
4397                     specialElCache.push({
4398                         id: id,
4399                         el: el
4400                     });
4401                     skip = true;
4402                 }
4403             }else{
4404                 id = Ext.id(el);
4405             }
4406             if(!Ext.elCache[id]){
4407                 Ext.Element.addToCache(new Ext.Element(el), id);
4408                 if(skip){
4409                     Ext.elCache[id].skipGC = true;
4410                 }
4411             }
4412         }
4413         return id;
4414      }
4415
4416     
4417     function addListener(el, ename, fn, task, wrap, scope){
4418         el = Ext.getDom(el);
4419         var id = getId(el),
4420             es = Ext.elCache[id].events,
4421             wfn;
4422
4423         wfn = E.on(el, ename, wrap);
4424         es[ename] = es[ename] || [];
4425
4426         
4427         es[ename].push([fn, wrap, scope, wfn, task]);
4428
4429         
4430         
4431
4432         
4433         if(el.addEventListener && ename == "mousewheel"){
4434             var args = ["DOMMouseScroll", wrap, false];
4435             el.addEventListener.apply(el, args);
4436             Ext.EventManager.addListener(WINDOW, 'unload', function(){
4437                 el.removeEventListener.apply(el, args);
4438             });
4439         }
4440
4441         
4442         if(el == DOC && ename == "mousedown"){
4443             Ext.EventManager.stoppedMouseDownEvent.addListener(wrap);
4444         }
4445     }
4446
4447     function doScrollChk(){
4448         
4449         if(window != top){
4450             return false;
4451         }
4452
4453         try{
4454             DOC.documentElement.doScroll('left');
4455         }catch(e){
4456              return false;
4457         }
4458
4459         fireDocReady();
4460         return true;
4461     }
4462     
4463     function checkReadyState(e){
4464
4465         if(Ext.isIE && doScrollChk()){
4466             return true;
4467         }
4468         if(DOC.readyState == COMPLETE){
4469             fireDocReady();
4470             return true;
4471         }
4472         docReadyState || (docReadyProcId = setTimeout(arguments.callee, 2));
4473         return false;
4474     }
4475
4476     var styles;
4477     function checkStyleSheets(e){
4478         styles || (styles = Ext.query('style, link[rel=stylesheet]'));
4479         if(styles.length == DOC.styleSheets.length){
4480             fireDocReady();
4481             return true;
4482         }
4483         docReadyState || (docReadyProcId = setTimeout(arguments.callee, 2));
4484         return false;
4485     }
4486
4487     function OperaDOMContentLoaded(e){
4488         DOC.removeEventListener(DOMCONTENTLOADED, arguments.callee, false);
4489         checkStyleSheets();
4490     }
4491
4492     function fireDocReady(e){
4493         if(!docReadyState){
4494             docReadyState = true; 
4495
4496             if(docReadyProcId){
4497                 clearTimeout(docReadyProcId);
4498             }
4499             if(DETECT_NATIVE) {
4500                 DOC.removeEventListener(DOMCONTENTLOADED, fireDocReady, false);
4501             }
4502             if(Ext.isIE && checkReadyState.bindIE){  
4503                 DOC.detachEvent('onreadystatechange', checkReadyState);
4504             }
4505             E.un(WINDOW, "load", arguments.callee);
4506         }
4507         if(docReadyEvent && !Ext.isReady){
4508             Ext.isReady = true;
4509             docReadyEvent.fire();
4510             docReadyEvent.listeners = [];
4511         }
4512
4513     }
4514
4515     function initDocReady(){
4516         docReadyEvent || (docReadyEvent = new Ext.util.Event());
4517         if (DETECT_NATIVE) {
4518             DOC.addEventListener(DOMCONTENTLOADED, fireDocReady, false);
4519         }
4520         
4521         if (Ext.isIE){
4522             
4523             
4524             if(!checkReadyState()){
4525                 checkReadyState.bindIE = true;
4526                 DOC.attachEvent('onreadystatechange', checkReadyState);
4527             }
4528
4529         }else if(Ext.isOpera ){
4530             
4531
4532             
4533             (DOC.readyState == COMPLETE && checkStyleSheets()) ||
4534                 DOC.addEventListener(DOMCONTENTLOADED, OperaDOMContentLoaded, false);
4535
4536         }else if (Ext.isWebKit){
4537             
4538             checkReadyState();
4539         }
4540         
4541         E.on(WINDOW, "load", fireDocReady);
4542     }
4543
4544     function createTargeted(h, o){
4545         return function(){
4546             var args = Ext.toArray(arguments);
4547             if(o.target == Ext.EventObject.setEvent(args[0]).target){
4548                 h.apply(this, args);
4549             }
4550         };
4551     }
4552
4553     function createBuffered(h, o, task){
4554         return function(e){
4555             
4556             task.delay(o.buffer, h, null, [new Ext.EventObjectImpl(e)]);
4557         };
4558     }
4559
4560     function createSingle(h, el, ename, fn, scope){
4561         return function(e){
4562             Ext.EventManager.removeListener(el, ename, fn, scope);
4563             h(e);
4564         };
4565     }
4566
4567     function createDelayed(h, o, fn){
4568         return function(e){
4569             var task = new Ext.util.DelayedTask(h);
4570             if(!fn.tasks) {
4571                 fn.tasks = [];
4572             }
4573             fn.tasks.push(task);
4574             task.delay(o.delay || 10, h, null, [new Ext.EventObjectImpl(e)]);
4575         };
4576     }
4577
4578     function listen(element, ename, opt, fn, scope){
4579         var o = (!opt || typeof opt == "boolean") ? {} : opt,
4580             el = Ext.getDom(element), task;
4581
4582         fn = fn || o.fn;
4583         scope = scope || o.scope;
4584
4585         if(!el){
4586             throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
4587         }
4588         function h(e){
4589             
4590             if(!Ext){
4591                 return;
4592             }
4593             e = Ext.EventObject.setEvent(e);
4594             var t;
4595             if (o.delegate) {
4596                 if(!(t = e.getTarget(o.delegate, el))){
4597                     return;
4598                 }
4599             } else {
4600                 t = e.target;
4601             }
4602             if (o.stopEvent) {
4603                 e.stopEvent();
4604             }
4605             if (o.preventDefault) {
4606                e.preventDefault();
4607             }
4608             if (o.stopPropagation) {
4609                 e.stopPropagation();
4610             }
4611             if (o.normalized === false) {
4612                 e = e.browserEvent;
4613             }
4614
4615             fn.call(scope || el, e, t, o);
4616         }
4617         if(o.target){
4618             h = createTargeted(h, o);
4619         }
4620         if(o.delay){
4621             h = createDelayed(h, o, fn);
4622         }
4623         if(o.single){
4624             h = createSingle(h, el, ename, fn, scope);
4625         }
4626         if(o.buffer){
4627             task = new Ext.util.DelayedTask(h);
4628             h = createBuffered(h, o, task);
4629         }
4630
4631         addListener(el, ename, fn, task, h, scope);
4632         return h;
4633     }
4634
4635     var pub = {
4636         
4637         addListener : function(element, eventName, fn, scope, options){
4638             if(typeof eventName == 'object'){
4639                 var o = eventName, e, val;
4640                 for(e in o){
4641                     val = o[e];
4642                     if(!propRe.test(e)){
4643                         if(Ext.isFunction(val)){
4644                             
4645                             listen(element, e, o, val, o.scope);
4646                         }else{
4647                             
4648                             listen(element, e, val);
4649                         }
4650                     }
4651                 }
4652             } else {
4653                 listen(element, eventName, options, fn, scope);
4654             }
4655         },
4656
4657         
4658         removeListener : function(el, eventName, fn, scope){
4659             el = Ext.getDom(el);
4660             var id = getId(el),
4661                 f = el && (Ext.elCache[id].events)[eventName] || [],
4662                 wrap, i, l, k, len, fnc;
4663
4664             for (i = 0, len = f.length; i < len; i++) {
4665
4666                 
4667                 if (Ext.isArray(fnc = f[i]) && fnc[0] == fn && (!scope || fnc[2] == scope)) {
4668                     if(fnc[4]) {
4669                         fnc[4].cancel();
4670                     }
4671                     k = fn.tasks && fn.tasks.length;
4672                     if(k) {
4673                         while(k--) {
4674                             fn.tasks[k].cancel();
4675                         }
4676                         delete fn.tasks;
4677                     }
4678                     wrap = fnc[1];
4679                     E.un(el, eventName, E.extAdapter ? fnc[3] : wrap);
4680
4681                     
4682                     if(wrap && el.addEventListener && eventName == "mousewheel"){
4683                         el.removeEventListener("DOMMouseScroll", wrap, false);
4684                     }
4685
4686                     
4687                     if(wrap && el == DOC && eventName == "mousedown"){
4688                         Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
4689                     }
4690
4691                     f.splice(i, 1);
4692                     if (f.length === 0) {
4693                         delete Ext.elCache[id].events[eventName];
4694                     }
4695                     for (k in Ext.elCache[id].events) {
4696                         return false;
4697                     }
4698                     Ext.elCache[id].events = {};
4699                     return false;
4700                 }
4701             }
4702         },
4703
4704         
4705         removeAll : function(el){
4706             el = Ext.getDom(el);
4707             var id = getId(el),
4708                 ec = Ext.elCache[id] || {},
4709                 es = ec.events || {},
4710                 f, i, len, ename, fn, k, wrap;
4711
4712             for(ename in es){
4713                 if(es.hasOwnProperty(ename)){
4714                     f = es[ename];
4715                     
4716                     for (i = 0, len = f.length; i < len; i++) {
4717                         fn = f[i];
4718                         if(fn[4]) {
4719                             fn[4].cancel();
4720                         }
4721                         if(fn[0].tasks && (k = fn[0].tasks.length)) {
4722                             while(k--) {
4723                                 fn[0].tasks[k].cancel();
4724                             }
4725                             delete fn.tasks;
4726                         }
4727                         wrap =  fn[1];
4728                         E.un(el, ename, E.extAdapter ? fn[3] : wrap);
4729
4730                         
4731                         if(el.addEventListener && wrap && ename == "mousewheel"){
4732                             el.removeEventListener("DOMMouseScroll", wrap, false);
4733                         }
4734
4735                         
4736                         if(wrap && el == DOC &&  ename == "mousedown"){
4737                             Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
4738                         }
4739                     }
4740                 }
4741             }
4742             if (Ext.elCache[id]) {
4743                 Ext.elCache[id].events = {};
4744             }
4745         },
4746
4747         getListeners : function(el, eventName) {
4748             el = Ext.getDom(el);
4749             var id = getId(el),
4750                 ec = Ext.elCache[id] || {},
4751                 es = ec.events || {},
4752                 results = [];
4753             if (es && es[eventName]) {
4754                 return es[eventName];
4755             } else {
4756                 return null;
4757             }
4758         },
4759
4760         purgeElement : function(el, recurse, eventName) {
4761             el = Ext.getDom(el);
4762             var id = getId(el),
4763                 ec = Ext.elCache[id] || {},
4764                 es = ec.events || {},
4765                 i, f, len;
4766             if (eventName) {
4767                 if (es && es.hasOwnProperty(eventName)) {
4768                     f = es[eventName];
4769                     for (i = 0, len = f.length; i < len; i++) {
4770                         Ext.EventManager.removeListener(el, eventName, f[i][0]);
4771                     }
4772                 }
4773             } else {
4774                 Ext.EventManager.removeAll(el);
4775             }
4776             if (recurse && el && el.childNodes) {
4777                 for (i = 0, len = el.childNodes.length; i < len; i++) {
4778                     Ext.EventManager.purgeElement(el.childNodes[i], recurse, eventName);
4779                 }
4780             }
4781         },
4782
4783         _unload : function() {
4784             var el;
4785             for (el in Ext.elCache) {
4786                 Ext.EventManager.removeAll(el);
4787             }
4788             delete Ext.elCache;
4789             delete Ext.Element._flyweights;
4790
4791             
4792             var c,
4793                 conn,
4794                 tid,
4795                 ajax = Ext.lib.Ajax;
4796             (typeof ajax.conn == 'object') ? conn = ajax.conn : conn = {};
4797             for (tid in conn) {
4798                 c = conn[tid];
4799                 if (c) {
4800                     ajax.abort({conn: c, tId: tid});
4801                 }
4802             }
4803         },
4804         
4805         onDocumentReady : function(fn, scope, options){
4806             if (Ext.isReady) { 
4807                 docReadyEvent || (docReadyEvent = new Ext.util.Event());
4808                 docReadyEvent.addListener(fn, scope, options);
4809                 docReadyEvent.fire();
4810                 docReadyEvent.listeners = [];
4811             } else {
4812                 if (!docReadyEvent) {
4813                     initDocReady();
4814                 }
4815                 options = options || {};
4816                 options.delay = options.delay || 1;
4817                 docReadyEvent.addListener(fn, scope, options);
4818             }
4819         },
4820
4821         
4822         fireDocReady  : fireDocReady
4823     };
4824      
4825     pub.on = pub.addListener;
4826     
4827     pub.un = pub.removeListener;
4828
4829     pub.stoppedMouseDownEvent = new Ext.util.Event();
4830     return pub;
4831 }();
4832
4833 Ext.onReady = Ext.EventManager.onDocumentReady;
4834
4835
4836
4837 (function(){
4838     var initExtCss = function() {
4839         
4840         var bd = document.body || document.getElementsByTagName('body')[0];
4841         if (!bd) {
4842             return false;
4843         }
4844         
4845         var cls = [' ',
4846                 Ext.isIE ? "ext-ie " + (Ext.isIE6 ? 'ext-ie6' : (Ext.isIE7 ? 'ext-ie7' : 'ext-ie8'))
4847                 : Ext.isGecko ? "ext-gecko " + (Ext.isGecko2 ? 'ext-gecko2' : 'ext-gecko3')
4848                 : Ext.isOpera ? "ext-opera"
4849                 : Ext.isWebKit ? "ext-webkit" : ""];
4850
4851         if (Ext.isSafari) {
4852             cls.push("ext-safari " + (Ext.isSafari2 ? 'ext-safari2' : (Ext.isSafari3 ? 'ext-safari3' : 'ext-safari4')));
4853         } else if(Ext.isChrome) {
4854             cls.push("ext-chrome");
4855         }
4856
4857         if (Ext.isMac) {
4858             cls.push("ext-mac");
4859         }
4860         if (Ext.isLinux) {
4861             cls.push("ext-linux");
4862         }
4863
4864         
4865         if (Ext.isStrict || Ext.isBorderBox) {
4866             var p = bd.parentNode;
4867             if (p) {
4868                 Ext.fly(p, '_internal').addClass(((Ext.isStrict && Ext.isIE ) || (!Ext.enableForcedBoxModel && !Ext.isIE)) ? ' ext-strict' : ' ext-border-box');
4869             }
4870         }
4871         
4872         
4873         if (Ext.enableForcedBoxModel && !Ext.isIE) {
4874             Ext.isForcedBorderBox = true;
4875             cls.push("ext-forced-border-box");
4876         }
4877         
4878         Ext.fly(bd, '_internal').addClass(cls);
4879         return true;
4880     };
4881     
4882     if (!initExtCss()) {
4883         Ext.onReady(initExtCss);
4884     }
4885 })();
4886
4887
4888 (function(){
4889     var supports = Ext.apply(Ext.supports, {
4890         
4891         correctRightMargin: true,
4892         
4893         
4894         correctTransparentColor: true,
4895         
4896         
4897         cssFloat: true
4898     });
4899     
4900     var supportTests = function(){
4901             var div = document.createElement('div'),
4902                 doc = document,
4903                 view,
4904                 last;
4905                 
4906             div.innerHTML = '<div style="height:30px;width:50px;"><div style="height:20px;width:20px;"></div></div><div style="float:left;background-color:transparent;">';
4907             doc.body.appendChild(div);
4908             last = div.lastChild;
4909             
4910             if((view = doc.defaultView)){
4911                 if(view.getComputedStyle(div.firstChild.firstChild, null).marginRight != '0px'){
4912                     supports.correctRightMargin = false;
4913                 }
4914                 if(view.getComputedStyle(last, null).backgroundColor != 'transparent'){
4915                     supports.correctTransparentColor = false;
4916                 }
4917             }
4918             supports.cssFloat = !!last.style.cssFloat;
4919             doc.body.removeChild(div);
4920     };
4921     
4922     if (Ext.isReady) {
4923         supportTests();    
4924     } else {
4925         Ext.onReady(supportTests);
4926     }
4927 })();
4928
4929
4930
4931 Ext.EventObject = function(){
4932     var E = Ext.lib.Event,
4933         clickRe = /(dbl)?click/,
4934         
4935         safariKeys = {
4936             3 : 13, 
4937             63234 : 37, 
4938             63235 : 39, 
4939             63232 : 38, 
4940             63233 : 40, 
4941             63276 : 33, 
4942             63277 : 34, 
4943             63272 : 46, 
4944             63273 : 36, 
4945             63275 : 35  
4946         },
4947         
4948         btnMap = Ext.isIE ? {1:0,4:1,2:2} : {0:0,1:1,2:2};
4949
4950     Ext.EventObjectImpl = function(e){
4951         if(e){
4952             this.setEvent(e.browserEvent || e);
4953         }
4954     };
4955
4956     Ext.EventObjectImpl.prototype = {
4957            
4958         setEvent : function(e){
4959             var me = this;
4960             if(e == me || (e && e.browserEvent)){ 
4961                 return e;
4962             }
4963             me.browserEvent = e;
4964             if(e){
4965                 
4966                 me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);
4967                 if(clickRe.test(e.type) && me.button == -1){
4968                     me.button = 0;
4969                 }
4970                 me.type = e.type;
4971                 me.shiftKey = e.shiftKey;
4972                 
4973                 me.ctrlKey = e.ctrlKey || e.metaKey || false;
4974                 me.altKey = e.altKey;
4975                 
4976                 me.keyCode = e.keyCode;
4977                 me.charCode = e.charCode;
4978                 
4979                 me.target = E.getTarget(e);
4980                 
4981                 me.xy = E.getXY(e);
4982             }else{
4983                 me.button = -1;
4984                 me.shiftKey = false;
4985                 me.ctrlKey = false;
4986                 me.altKey = false;
4987                 me.keyCode = 0;
4988                 me.charCode = 0;
4989                 me.target = null;
4990                 me.xy = [0, 0];
4991             }
4992             return me;
4993         },
4994
4995         
4996         stopEvent : function(){
4997             var me = this;
4998             if(me.browserEvent){
4999                 if(me.browserEvent.type == 'mousedown'){
5000                     Ext.EventManager.stoppedMouseDownEvent.fire(me);
5001                 }
5002                 E.stopEvent(me.browserEvent);
5003             }
5004         },
5005
5006         
5007         preventDefault : function(){
5008             if(this.browserEvent){
5009                 E.preventDefault(this.browserEvent);
5010             }
5011         },
5012
5013         
5014         stopPropagation : function(){
5015             var me = this;
5016             if(me.browserEvent){
5017                 if(me.browserEvent.type == 'mousedown'){
5018                     Ext.EventManager.stoppedMouseDownEvent.fire(me);
5019                 }
5020                 E.stopPropagation(me.browserEvent);
5021             }
5022         },
5023
5024         
5025         getCharCode : function(){
5026             return this.charCode || this.keyCode;
5027         },
5028
5029         
5030         getKey : function(){
5031             return this.normalizeKey(this.keyCode || this.charCode);
5032         },
5033
5034         
5035         normalizeKey: function(k){
5036             return Ext.isSafari ? (safariKeys[k] || k) : k;
5037         },
5038
5039         
5040         getPageX : function(){
5041             return this.xy[0];
5042         },
5043
5044         
5045         getPageY : function(){
5046             return this.xy[1];
5047         },
5048
5049         
5050         getXY : function(){
5051             return this.xy;
5052         },
5053
5054         
5055         getTarget : function(selector, maxDepth, returnEl){
5056             return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);
5057         },
5058
5059         
5060         getRelatedTarget : function(){
5061             return this.browserEvent ? E.getRelatedTarget(this.browserEvent) : null;
5062         },
5063
5064         
5065         getWheelDelta : function(){
5066             var e = this.browserEvent;
5067             var delta = 0;
5068             if(e.wheelDelta){ 
5069                 delta = e.wheelDelta/120;
5070             }else if(e.detail){ 
5071                 delta = -e.detail/3;
5072             }
5073             return delta;
5074         },
5075
5076         
5077         within : function(el, related, allowEl){
5078             if(el){
5079                 var t = this[related ? "getRelatedTarget" : "getTarget"]();
5080                 return t && ((allowEl ? (t == Ext.getDom(el)) : false) || Ext.fly(el).contains(t));
5081             }
5082             return false;
5083         }
5084      };
5085
5086     return new Ext.EventObjectImpl();
5087 }();
5088
5089 Ext.Loader = Ext.apply({}, {
5090     
5091     load: function(fileList, callback, scope, preserveOrder) {
5092         var scope       = scope || this,
5093             head        = document.getElementsByTagName("head")[0],
5094             fragment    = document.createDocumentFragment(),
5095             numFiles    = fileList.length,
5096             loadedFiles = 0,
5097             me          = this;
5098         
5099         
5100         var loadFileIndex = function(index) {
5101             head.appendChild(
5102                 me.buildScriptTag(fileList[index], onFileLoaded)
5103             );
5104         };
5105         
5106         
5107         var onFileLoaded = function() {
5108             loadedFiles ++;
5109             
5110             
5111             if (numFiles == loadedFiles && typeof callback == 'function') {
5112                 callback.call(scope);
5113             } else {
5114                 if (preserveOrder === true) {
5115                     loadFileIndex(loadedFiles);
5116                 }
5117             }
5118         };
5119         
5120         if (preserveOrder === true) {
5121             loadFileIndex.call(this, 0);
5122         } else {
5123             
5124             Ext.each(fileList, function(file, index) {
5125                 fragment.appendChild(
5126                     this.buildScriptTag(file, onFileLoaded)
5127                 );  
5128             }, this);
5129             
5130             head.appendChild(fragment);
5131         }
5132     },
5133     
5134     
5135     buildScriptTag: function(filename, callback) {
5136         var script  = document.createElement('script');
5137         script.type = "text/javascript";
5138         script.src  = filename;
5139         
5140         
5141         if (script.readyState) {
5142             script.onreadystatechange = function() {
5143                 if (script.readyState == "loaded" || script.readyState == "complete") {
5144                     script.onreadystatechange = null;
5145                     callback();
5146                 }
5147             };
5148         } else {
5149             script.onload = callback;
5150         }    
5151         
5152         return script;
5153     }
5154 });
5155
5156
5157 Ext.ns("Ext.grid", "Ext.list", "Ext.dd", "Ext.tree", "Ext.form", "Ext.menu",
5158        "Ext.state", "Ext.layout", "Ext.app", "Ext.ux", "Ext.chart", "Ext.direct");
5159     
5160
5161 Ext.apply(Ext, function(){
5162     var E = Ext,
5163         idSeed = 0,
5164         scrollWidth = null;
5165
5166     return {
5167         
5168         emptyFn : function(){},
5169
5170         
5171         BLANK_IMAGE_URL : Ext.isIE6 || Ext.isIE7 || Ext.isAir ?
5172                             'http:/' + '/www.extjs.com/s.gif' :
5173                             'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
5174
5175         extendX : function(supr, fn){
5176             return Ext.extend(supr, fn(supr.prototype));
5177         },
5178
5179         
5180         getDoc : function(){
5181             return Ext.get(document);
5182         },
5183
5184         
5185         num : function(v, defaultValue){
5186             v = Number(Ext.isEmpty(v) || Ext.isArray(v) || typeof v == 'boolean' || (typeof v == 'string' && v.trim().length == 0) ? NaN : v);
5187             return isNaN(v) ? defaultValue : v;
5188         },
5189
5190         
5191         value : function(v, defaultValue, allowBlank){
5192             return Ext.isEmpty(v, allowBlank) ? defaultValue : v;
5193         },
5194
5195         
5196         escapeRe : function(s) {
5197             return s.replace(/([-.*+?^${}()|[\]\/\\])/g, "\\$1");
5198         },
5199
5200         sequence : function(o, name, fn, scope){
5201             o[name] = o[name].createSequence(fn, scope);
5202         },
5203
5204         
5205         addBehaviors : function(o){
5206             if(!Ext.isReady){
5207                 Ext.onReady(function(){
5208                     Ext.addBehaviors(o);
5209                 });
5210             } else {
5211                 var cache = {}, 
5212                     parts,
5213                     b,
5214                     s;
5215                 for (b in o) {
5216                     if ((parts = b.split('@'))[1]) { 
5217                         s = parts[0];
5218                         if(!cache[s]){
5219                             cache[s] = Ext.select(s);
5220                         }
5221                         cache[s].on(parts[1], o[b]);
5222                     }
5223                 }
5224                 cache = null;
5225             }
5226         },
5227
5228         
5229         getScrollBarWidth: function(force){
5230             if(!Ext.isReady){
5231                 return 0;
5232             }
5233
5234             if(force === true || scrollWidth === null){
5235                     
5236                 var div = Ext.getBody().createChild('<div class="x-hide-offsets" style="width:100px;height:50px;overflow:hidden;"><div style="height:200px;"></div></div>'),
5237                     child = div.child('div', true);
5238                 var w1 = child.offsetWidth;
5239                 div.setStyle('overflow', (Ext.isWebKit || Ext.isGecko) ? 'auto' : 'scroll');
5240                 var w2 = child.offsetWidth;
5241                 div.remove();
5242                 
5243                 scrollWidth = w1 - w2 + 2;
5244             }
5245             return scrollWidth;
5246         },
5247
5248
5249         
5250         combine : function(){
5251             var as = arguments, l = as.length, r = [];
5252             for(var i = 0; i < l; i++){
5253                 var a = as[i];
5254                 if(Ext.isArray(a)){
5255                     r = r.concat(a);
5256                 }else if(a.length !== undefined && !a.substr){
5257                     r = r.concat(Array.prototype.slice.call(a, 0));
5258                 }else{
5259                     r.push(a);
5260                 }
5261             }
5262             return r;
5263         },
5264
5265         
5266         copyTo : function(dest, source, names){
5267             if(typeof names == 'string'){
5268                 names = names.split(/[,;\s]/);
5269             }
5270             Ext.each(names, function(name){
5271                 if(source.hasOwnProperty(name)){
5272                     dest[name] = source[name];
5273                 }
5274             }, this);
5275             return dest;
5276         },
5277
5278         
5279         destroy : function(){
5280             Ext.each(arguments, function(arg){
5281                 if(arg){
5282                     if(Ext.isArray(arg)){
5283                         this.destroy.apply(this, arg);
5284                     }else if(typeof arg.destroy == 'function'){
5285                         arg.destroy();
5286                     }else if(arg.dom){
5287                         arg.remove();
5288                     }
5289                 }
5290             }, this);
5291         },
5292
5293         
5294         destroyMembers : function(o, arg1, arg2, etc){
5295             for(var i = 1, a = arguments, len = a.length; i < len; i++) {
5296                 Ext.destroy(o[a[i]]);
5297                 delete o[a[i]];
5298             }
5299         },
5300
5301         
5302         clean : function(arr){
5303             var ret = [];
5304             Ext.each(arr, function(v){
5305                 if(!!v){
5306                     ret.push(v);
5307                 }
5308             });
5309             return ret;
5310         },
5311
5312         
5313         unique : function(arr){
5314             var ret = [],
5315                 collect = {};
5316
5317             Ext.each(arr, function(v) {
5318                 if(!collect[v]){
5319                     ret.push(v);
5320                 }
5321                 collect[v] = true;
5322             });
5323             return ret;
5324         },
5325
5326         
5327         flatten : function(arr){
5328             var worker = [];
5329             function rFlatten(a) {
5330                 Ext.each(a, function(v) {
5331                     if(Ext.isArray(v)){
5332                         rFlatten(v);
5333                     }else{
5334                         worker.push(v);
5335                     }
5336                 });
5337                 return worker;
5338             }
5339             return rFlatten(arr);
5340         },
5341
5342         
5343         min : function(arr, comp){
5344             var ret = arr[0];
5345             comp = comp || function(a,b){ return a < b ? -1 : 1; };
5346             Ext.each(arr, function(v) {
5347                 ret = comp(ret, v) == -1 ? ret : v;
5348             });
5349             return ret;
5350         },
5351
5352         
5353         max : function(arr, comp){
5354             var ret = arr[0];
5355             comp = comp || function(a,b){ return a > b ? 1 : -1; };
5356             Ext.each(arr, function(v) {
5357                 ret = comp(ret, v) == 1 ? ret : v;
5358             });
5359             return ret;
5360         },
5361
5362         
5363         mean : function(arr){
5364            return arr.length > 0 ? Ext.sum(arr) / arr.length : undefined;
5365         },
5366
5367         
5368         sum : function(arr){
5369            var ret = 0;
5370            Ext.each(arr, function(v) {
5371                ret += v;
5372            });
5373            return ret;
5374         },
5375
5376         
5377         partition : function(arr, truth){
5378             var ret = [[],[]];
5379             Ext.each(arr, function(v, i, a) {
5380                 ret[ (truth && truth(v, i, a)) || (!truth && v) ? 0 : 1].push(v);
5381             });
5382             return ret;
5383         },
5384
5385         
5386         invoke : function(arr, methodName){
5387             var ret = [],
5388                 args = Array.prototype.slice.call(arguments, 2);
5389             Ext.each(arr, function(v,i) {
5390                 if (v && typeof v[methodName] == 'function') {
5391                     ret.push(v[methodName].apply(v, args));
5392                 } else {
5393                     ret.push(undefined);
5394                 }
5395             });
5396             return ret;
5397         },
5398
5399         
5400         pluck : function(arr, prop){
5401             var ret = [];
5402             Ext.each(arr, function(v) {
5403                 ret.push( v[prop] );
5404             });
5405             return ret;
5406         },
5407
5408         
5409         zip : function(){
5410             var parts = Ext.partition(arguments, function( val ){ return typeof val != 'function'; }),
5411                 arrs = parts[0],
5412                 fn = parts[1][0],
5413                 len = Ext.max(Ext.pluck(arrs, "length")),
5414                 ret = [];
5415
5416             for (var i = 0; i < len; i++) {
5417                 ret[i] = [];
5418                 if(fn){
5419                     ret[i] = fn.apply(fn, Ext.pluck(arrs, i));
5420                 }else{
5421                     for (var j = 0, aLen = arrs.length; j < aLen; j++){
5422                         ret[i].push( arrs[j][i] );
5423                     }
5424                 }
5425             }
5426             return ret;
5427         },
5428
5429         
5430         getCmp : function(id){
5431             return Ext.ComponentMgr.get(id);
5432         },
5433
5434         
5435         useShims: E.isIE6 || (E.isMac && E.isGecko2),
5436
5437         
5438         
5439         type : function(o){
5440             if(o === undefined || o === null){
5441                 return false;
5442             }
5443             if(o.htmlElement){
5444                 return 'element';
5445             }
5446             var t = typeof o;
5447             if(t == 'object' && o.nodeName) {
5448                 switch(o.nodeType) {
5449                     case 1: return 'element';
5450                     case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
5451                 }
5452             }
5453             if(t == 'object' || t == 'function') {
5454                 switch(o.constructor) {
5455                     case Array: return 'array';
5456                     case RegExp: return 'regexp';
5457                     case Date: return 'date';
5458                 }
5459                 if(typeof o.length == 'number' && typeof o.item == 'function') {
5460                     return 'nodelist';
5461                 }
5462             }
5463             return t;
5464         },
5465
5466         intercept : function(o, name, fn, scope){
5467             o[name] = o[name].createInterceptor(fn, scope);
5468         },
5469
5470         
5471         callback : function(cb, scope, args, delay){
5472             if(typeof cb == 'function'){
5473                 if(delay){
5474                     cb.defer(delay, scope, args || []);
5475                 }else{
5476                     cb.apply(scope, args || []);
5477                 }
5478             }
5479         }
5480     };
5481 }());
5482
5483
5484 Ext.apply(Function.prototype, {
5485     
5486     createSequence : function(fcn, scope){
5487         var method = this;
5488         return (typeof fcn != 'function') ?
5489                 this :
5490                 function(){
5491                     var retval = method.apply(this || window, arguments);
5492                     fcn.apply(scope || this || window, arguments);
5493                     return retval;
5494                 };
5495     }
5496 });
5497
5498
5499
5500 Ext.applyIf(String, {
5501
5502     
5503     escape : function(string) {
5504         return string.replace(/('|\\)/g, "\\$1");
5505     },
5506
5507     
5508     leftPad : function (val, size, ch) {
5509         var result = String(val);
5510         if(!ch) {
5511             ch = " ";
5512         }
5513         while (result.length < size) {
5514             result = ch + result;
5515         }
5516         return result;
5517     }
5518 });
5519
5520
5521 String.prototype.toggle = function(value, other){
5522     return this == value ? other : value;
5523 };
5524
5525
5526 String.prototype.trim = function(){
5527     var re = /^\s+|\s+$/g;
5528     return function(){ return this.replace(re, ""); };
5529 }();
5530
5531
5532
5533 Date.prototype.getElapsed = function(date) {
5534     return Math.abs((date || new Date()).getTime()-this.getTime());
5535 };
5536
5537
5538
5539 Ext.applyIf(Number.prototype, {
5540     
5541     constrain : function(min, max){
5542         return Math.min(Math.max(this, min), max);
5543     }
5544 });
5545 Ext.lib.Dom.getRegion = function(el) {
5546     return Ext.lib.Region.getRegion(el);
5547 };      Ext.lib.Region = function(t, r, b, l) {
5548                 var me = this;
5549         me.top = t;
5550         me[1] = t;
5551         me.right = r;
5552         me.bottom = b;
5553         me.left = l;
5554         me[0] = l;
5555     };
5556
5557     Ext.lib.Region.prototype = {
5558         contains : function(region) {
5559                 var me = this;
5560             return ( region.left >= me.left &&
5561                      region.right <= me.right &&
5562                      region.top >= me.top &&
5563                      region.bottom <= me.bottom );
5564
5565         },
5566
5567         getArea : function() {
5568                 var me = this;
5569             return ( (me.bottom - me.top) * (me.right - me.left) );
5570         },
5571
5572         intersect : function(region) {
5573             var me = this,
5574                 t = Math.max(me.top, region.top),
5575                 r = Math.min(me.right, region.right),
5576                 b = Math.min(me.bottom, region.bottom),
5577                 l = Math.max(me.left, region.left);
5578
5579             if (b >= t && r >= l) {
5580                 return new Ext.lib.Region(t, r, b, l);
5581             }
5582         },
5583         
5584         union : function(region) {
5585                 var me = this,
5586                 t = Math.min(me.top, region.top),
5587                 r = Math.max(me.right, region.right),
5588                 b = Math.max(me.bottom, region.bottom),
5589                 l = Math.min(me.left, region.left);
5590
5591             return new Ext.lib.Region(t, r, b, l);
5592         },
5593
5594         constrainTo : function(r) {
5595                 var me = this;
5596             me.top = me.top.constrain(r.top, r.bottom);
5597             me.bottom = me.bottom.constrain(r.top, r.bottom);
5598             me.left = me.left.constrain(r.left, r.right);
5599             me.right = me.right.constrain(r.left, r.right);
5600             return me;
5601         },
5602
5603         adjust : function(t, l, b, r) {
5604                 var me = this;
5605             me.top += t;
5606             me.left += l;
5607             me.right += r;
5608             me.bottom += b;
5609             return me;
5610         }
5611     };
5612
5613     Ext.lib.Region.getRegion = function(el) {
5614         var p = Ext.lib.Dom.getXY(el),
5615                 t = p[1],
5616                 r = p[0] + el.offsetWidth,
5617                 b = p[1] + el.offsetHeight,
5618                 l = p[0];
5619
5620         return new Ext.lib.Region(t, r, b, l);
5621     };  Ext.lib.Point = function(x, y) {
5622         if (Ext.isArray(x)) {
5623             y = x[1];
5624             x = x[0];
5625         }
5626         var me = this;
5627         me.x = me.right = me.left = me[0] = x;
5628         me.y = me.top = me.bottom = me[1] = y;
5629     };
5630
5631     Ext.lib.Point.prototype = new Ext.lib.Region();
5632
5633 Ext.apply(Ext.DomHelper,
5634 function(){
5635     var pub,
5636         afterbegin = 'afterbegin',
5637         afterend = 'afterend',
5638         beforebegin = 'beforebegin',
5639         beforeend = 'beforeend',
5640         confRe = /tag|children|cn|html$/i;
5641
5642     
5643     function doInsert(el, o, returnElement, pos, sibling, append){
5644         el = Ext.getDom(el);
5645         var newNode;
5646         if (pub.useDom) {
5647             newNode = createDom(o, null);
5648             if (append) {
5649                 el.appendChild(newNode);
5650             } else {
5651                 (sibling == 'firstChild' ? el : el.parentNode).insertBefore(newNode, el[sibling] || el);
5652             }
5653         } else {
5654             newNode = Ext.DomHelper.insertHtml(pos, el, Ext.DomHelper.createHtml(o));
5655         }
5656         return returnElement ? Ext.get(newNode, true) : newNode;
5657     }
5658
5659     
5660     
5661     function createDom(o, parentNode){
5662         var el,
5663             doc = document,
5664             useSet,
5665             attr,
5666             val,
5667             cn;
5668
5669         if (Ext.isArray(o)) {                       
5670             el = doc.createDocumentFragment(); 
5671             for (var i = 0, l = o.length; i < l; i++) {
5672                 createDom(o[i], el);
5673             }
5674         } else if (typeof o == 'string') {         
5675             el = doc.createTextNode(o);
5676         } else {
5677             el = doc.createElement( o.tag || 'div' );
5678             useSet = !!el.setAttribute; 
5679             for (var attr in o) {
5680                 if(!confRe.test(attr)){
5681                     val = o[attr];
5682                     if(attr == 'cls'){
5683                         el.className = val;
5684                     }else{
5685                         if(useSet){
5686                             el.setAttribute(attr, val);
5687                         }else{
5688                             el[attr] = val;
5689                         }
5690                     }
5691                 }
5692             }
5693             Ext.DomHelper.applyStyles(el, o.style);
5694
5695             if ((cn = o.children || o.cn)) {
5696                 createDom(cn, el);
5697             } else if (o.html) {
5698                 el.innerHTML = o.html;
5699             }
5700         }
5701         if(parentNode){
5702            parentNode.appendChild(el);
5703         }
5704         return el;
5705     }
5706
5707     pub = {
5708         
5709         createTemplate : function(o){
5710             var html = Ext.DomHelper.createHtml(o);
5711             return new Ext.Template(html);
5712         },
5713
5714         
5715         useDom : false,
5716
5717         
5718         insertBefore : function(el, o, returnElement){
5719             return doInsert(el, o, returnElement, beforebegin);
5720         },
5721
5722         
5723         insertAfter : function(el, o, returnElement){
5724             return doInsert(el, o, returnElement, afterend, 'nextSibling');
5725         },
5726
5727         
5728         insertFirst : function(el, o, returnElement){
5729             return doInsert(el, o, returnElement, afterbegin, 'firstChild');
5730         },
5731
5732         
5733         append: function(el, o, returnElement){
5734             return doInsert(el, o, returnElement, beforeend, '', true);
5735         },
5736
5737         
5738         createDom: createDom
5739     };
5740     return pub;
5741 }());
5742
5743 Ext.apply(Ext.Template.prototype, {
5744     
5745     disableFormats : false,
5746     
5747
5748     
5749     re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
5750     argsRe : /^\s*['"](.*)["']\s*$/,
5751     compileARe : /\\/g,
5752     compileBRe : /(\r\n|\n)/g,
5753     compileCRe : /'/g,
5754
5755     /**
5756      * Returns an HTML fragment of this template with the specified values applied.
5757      * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
5758      * @return {String} The HTML fragment
5759      * @hide repeat doc
5760      */
5761     applyTemplate : function(values){
5762         var me = this,
5763             useF = me.disableFormats !== true,
5764             fm = Ext.util.Format,
5765             tpl = me;
5766
5767         if(me.compiled){
5768             return me.compiled(values);
5769         }
5770         function fn(m, name, format, args){
5771             if (format && useF) {
5772                 if (format.substr(0, 5) == "this.") {
5773                     return tpl.call(format.substr(5), values[name], values);
5774                 } else {
5775                     if (args) {
5776                         // quoted values are required for strings in compiled templates,
5777                         // but for non compiled we need to strip them
5778                         // quoted reversed for jsmin
5779                         var re = me.argsRe;
5780                         args = args.split(',');
5781                         for(var i = 0, len = args.length; i < len; i++){
5782                             args[i] = args[i].replace(re, "$1");
5783                         }
5784                         args = [values[name]].concat(args);
5785                     } else {
5786                         args = [values[name]];
5787                     }
5788                     return fm[format].apply(fm, args);
5789                 }
5790             } else {
5791                 return values[name] !== undefined ? values[name] : "";
5792             }
5793         }
5794         return me.html.replace(me.re, fn);
5795     },
5796
5797     /**
5798      * Compiles the template into an internal function, eliminating the RegEx overhead.
5799      * @return {Ext.Template} this
5800      * @hide repeat doc
5801      */
5802     compile : function(){
5803         var me = this,
5804             fm = Ext.util.Format,
5805             useF = me.disableFormats !== true,
5806             sep = Ext.isGecko ? "+" : ",",
5807             body;
5808
5809         function fn(m, name, format, args){
5810             if(format && useF){
5811                 args = args ? ',' + args : "";
5812                 if(format.substr(0, 5) != "this."){
5813                     format = "fm." + format + '(';
5814                 }else{
5815                     format = 'this.call("'+ format.substr(5) + '", ';
5816                     args = ", values";
5817                 }
5818             }else{
5819                 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
5820             }
5821             return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
5822         }
5823
5824         // branched to use + in gecko and [].join() in others
5825         if(Ext.isGecko){
5826             body = "this.compiled = function(values){ return '" +
5827                    me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn) +
5828                     "';};";
5829         }else{
5830             body = ["this.compiled = function(values){ return ['"];
5831             body.push(me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn));
5832             body.push("'].join('');};");
5833             body = body.join('');
5834         }
5835         eval(body);
5836         return me;
5837     },
5838
5839     // private function used to call members
5840     call : function(fnName, value, allValues){
5841         return this[fnName](value, allValues);
5842     }
5843 });
5844 Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
5845 /**
5846  * @class Ext.util.Functions
5847  * @singleton
5848  */
5849 Ext.util.Functions = {
5850     /**
5851      * Creates an interceptor function. The passed function is called before the original one. If it returns false,
5852      * the original one is not called. The resulting function returns the results of the original function.
5853      * The passed function is called with the parameters of the original function. Example usage:
5854      * <pre><code>
5855 var sayHi = function(name){
5856     alert('Hi, ' + name);
5857 }
5858
5859 sayHi('Fred'); // alerts "Hi, Fred"
5860
5861 // create a new function that validates input without
5862 // directly modifying the original function:
5863 var sayHiToFriend = Ext.createInterceptor(sayHi, function(name){
5864     return name == 'Brian';
5865 });
5866
5867 sayHiToFriend('Fred');  // no alert
5868 sayHiToFriend('Brian'); // alerts "Hi, Brian"
5869        </code></pre>
5870      * @param {Function} origFn The original function.
5871      * @param {Function} newFn The function to call before the original
5872      * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the passed function is executed.
5873      * <b>If omitted, defaults to the scope in which the original function is called or the browser window.</b>
5874      * @return {Function} The new function
5875      */
5876     createInterceptor: function(origFn, newFn, scope) { 
5877         var method = origFn;
5878         if (!Ext.isFunction(newFn)) {
5879             return origFn;
5880         }
5881         else {
5882             return function() {
5883                 var me = this,
5884                     args = arguments;
5885                 newFn.target = me;
5886                 newFn.method = origFn;
5887                 return (newFn.apply(scope || me || window, args) !== false) ?
5888                         origFn.apply(me || window, args) :
5889                         null;
5890             };
5891         }
5892     },
5893
5894     /**
5895      * Creates a delegate (callback) that sets the scope to obj.
5896      * Call directly on any function. Example: <code>Ext.createDelegate(this.myFunction, this, [arg1, arg2])</code>
5897      * Will create a function that is automatically scoped to obj so that the <tt>this</tt> variable inside the
5898      * callback points to obj. Example usage:
5899      * <pre><code>
5900 var sayHi = function(name){
5901     // Note this use of "this.text" here.  This function expects to
5902     // execute within a scope that contains a text property.  In this
5903     // example, the "this" variable is pointing to the btn object that
5904     // was passed in createDelegate below.
5905     alert('Hi, ' + name + '. You clicked the "' + this.text + '" button.');
5906 }
5907
5908 var btn = new Ext.Button({
5909     text: 'Say Hi',
5910     renderTo: Ext.getBody()
5911 });
5912
5913 // This callback will execute in the scope of the
5914 // button instance. Clicking the button alerts
5915 // "Hi, Fred. You clicked the "Say Hi" button."
5916 btn.on('click', Ext.createDelegate(sayHi, btn, ['Fred']));
5917        </code></pre>
5918      * @param {Function} fn The function to delegate.
5919      * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
5920      * <b>If omitted, defaults to the browser window.</b>
5921      * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
5922      * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
5923      * if a number the args are inserted at the specified position
5924      * @return {Function} The new function
5925      */
5926     createDelegate: function(fn, obj, args, appendArgs) {
5927         if (!Ext.isFunction(fn)) {
5928             return fn;
5929         }
5930         return function() {
5931             var callArgs = args || arguments;
5932             if (appendArgs === true) {
5933                 callArgs = Array.prototype.slice.call(arguments, 0);
5934                 callArgs = callArgs.concat(args);
5935             }
5936             else if (Ext.isNumber(appendArgs)) {
5937                 callArgs = Array.prototype.slice.call(arguments, 0);
5938                 // copy arguments first
5939                 var applyArgs = [appendArgs, 0].concat(args);
5940                 // create method call params
5941                 Array.prototype.splice.apply(callArgs, applyArgs);
5942                 // splice them in
5943             }
5944             return fn.apply(obj || window, callArgs);
5945         };
5946     },
5947
5948     /**
5949      * Calls this function after the number of millseconds specified, optionally in a specific scope. Example usage:
5950      * <pre><code>
5951 var sayHi = function(name){
5952     alert('Hi, ' + name);
5953 }
5954
5955 // executes immediately:
5956 sayHi('Fred');
5957
5958 // executes after 2 seconds:
5959 Ext.defer(sayHi, 2000, this, ['Fred']);
5960
5961 // this syntax is sometimes useful for deferring
5962 // execution of an anonymous function:
5963 Ext.defer(function(){
5964     alert('Anonymous');
5965 }, 100);
5966        </code></pre>
5967      * @param {Function} fn The function to defer.
5968      * @param {Number} millis The number of milliseconds for the setTimeout call (if less than or equal to 0 the function is executed immediately)
5969      * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
5970      * <b>If omitted, defaults to the browser window.</b>
5971      * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
5972      * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
5973      * if a number the args are inserted at the specified position
5974      * @return {Number} The timeout id that can be used with clearTimeout
5975      */
5976     defer: function(fn, millis, obj, args, appendArgs) {
5977         fn = Ext.util.Functions.createDelegate(fn, obj, args, appendArgs);
5978         if (millis > 0) {
5979             return setTimeout(fn, millis);
5980         }
5981         fn();
5982         return 0;
5983     },
5984
5985
5986     /**
5987      * Create a combined function call sequence of the original function + the passed function.
5988      * The resulting function returns the results of the original function.
5989      * The passed fcn is called with the parameters of the original function. Example usage:
5990      * 
5991
5992 var sayHi = function(name){
5993     alert('Hi, ' + name);
5994 }
5995
5996 sayHi('Fred'); // alerts "Hi, Fred"
5997
5998 var sayGoodbye = Ext.createSequence(sayHi, function(name){
5999     alert('Bye, ' + name);
6000 });
6001
6002 sayGoodbye('Fred'); // both alerts show
6003
6004      * @param {Function} origFn The original function.
6005      * @param {Function} newFn The function to sequence
6006      * @param {Object} scope (optional) The scope (this reference) in which the passed function is executed.
6007      * If omitted, defaults to the scope in which the original function is called or the browser window.
6008      * @return {Function} The new function
6009      */
6010     createSequence: function(origFn, newFn, scope) {
6011         if (!Ext.isFunction(newFn)) {
6012             return origFn;
6013         }
6014         else {
6015             return function() {
6016                 var retval = origFn.apply(this || window, arguments);
6017                 newFn.apply(scope || this || window, arguments);
6018                 return retval;
6019             };
6020         }
6021     }
6022 };
6023
6024 /**
6025  * Shorthand for {@link Ext.util.Functions#defer}   
6026  * @param {Function} fn The function to defer.
6027  * @param {Number} millis The number of milliseconds for the setTimeout call (if less than or equal to 0 the function is executed immediately)
6028  * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
6029  * <b>If omitted, defaults to the browser window.</b>
6030  * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
6031  * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
6032  * if a number the args are inserted at the specified position
6033  * @return {Number} The timeout id that can be used with clearTimeout
6034  * @member Ext
6035  * @method defer
6036  */
6037
6038 Ext.defer = Ext.util.Functions.defer;
6039
6040 /**
6041  * Shorthand for {@link Ext.util.Functions#createInterceptor}   
6042  * @param {Function} origFn The original function.
6043  * @param {Function} newFn The function to call before the original
6044  * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the passed function is executed.
6045  * <b>If omitted, defaults to the scope in which the original function is called or the browser window.</b>
6046  * @return {Function} The new function
6047  * @member Ext
6048  * @method defer
6049  */
6050
6051 Ext.createInterceptor = Ext.util.Functions.createInterceptor;
6052
6053 /**
6054  * Shorthand for {@link Ext.util.Functions#createSequence}
6055  * @param {Function} origFn The original function.
6056  * @param {Function} newFn The function to sequence
6057  * @param {Object} scope (optional) The scope (this reference) in which the passed function is executed.
6058  * If omitted, defaults to the scope in which the original function is called or the browser window.
6059  * @return {Function} The new function
6060  * @member Ext
6061  * @method defer
6062  */
6063
6064 Ext.createSequence = Ext.util.Functions.createSequence;
6065
6066 /**
6067  * Shorthand for {@link Ext.util.Functions#createDelegate}
6068  * @param {Function} fn The function to delegate.
6069  * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
6070  * <b>If omitted, defaults to the browser window.</b>
6071  * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
6072  * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
6073  * if a number the args are inserted at the specified position
6074  * @return {Function} The new function
6075  * @member Ext
6076  * @method defer
6077  */
6078 Ext.createDelegate = Ext.util.Functions.createDelegate;
6079 /**
6080  * @class Ext.util.Observable
6081  */
6082 Ext.apply(Ext.util.Observable.prototype, function(){
6083     // this is considered experimental (along with beforeMethod, afterMethod, removeMethodListener?)
6084     // allows for easier interceptor and sequences, including cancelling and overwriting the return value of the call
6085     // private
6086     function getMethodEvent(method){
6087         var e = (this.methodEvents = this.methodEvents ||
6088         {})[method], returnValue, v, cancel, obj = this;
6089
6090         if (!e) {
6091             this.methodEvents[method] = e = {};
6092             e.originalFn = this[method];
6093             e.methodName = method;
6094             e.before = [];
6095             e.after = [];
6096
6097             var makeCall = function(fn, scope, args){
6098                 if((v = fn.apply(scope || obj, args)) !== undefined){
6099                     if (typeof v == 'object') {
6100                         if(v.returnValue !== undefined){
6101                             returnValue = v.returnValue;
6102                         }else{
6103                             returnValue = v;
6104                         }
6105                         cancel = !!v.cancel;
6106                     }
6107                     else
6108                         if (v === false) {
6109                             cancel = true;
6110                         }
6111                         else {
6112                             returnValue = v;
6113                         }
6114                 }
6115             };
6116
6117             this[method] = function(){
6118                 var args = Array.prototype.slice.call(arguments, 0),
6119                     b;
6120                 returnValue = v = undefined;
6121                 cancel = false;
6122
6123                 for(var i = 0, len = e.before.length; i < len; i++){
6124                     b = e.before[i];
6125                     makeCall(b.fn, b.scope, args);
6126                     if (cancel) {
6127                         return returnValue;
6128                     }
6129                 }
6130
6131                 if((v = e.originalFn.apply(obj, args)) !== undefined){
6132                     returnValue = v;
6133                 }
6134
6135                 for(var i = 0, len = e.after.length; i < len; i++){
6136                     b = e.after[i];
6137                     makeCall(b.fn, b.scope, args);
6138                     if (cancel) {
6139                         return returnValue;
6140                     }
6141                 }
6142                 return returnValue;
6143             };
6144         }
6145         return e;
6146     }
6147
6148     return {
6149         // these are considered experimental
6150         // allows for easier interceptor and sequences, including cancelling and overwriting the return value of the call
6151         // adds an 'interceptor' called before the original method
6152         beforeMethod : function(method, fn, scope){
6153             getMethodEvent.call(this, method).before.push({
6154                 fn: fn,
6155                 scope: scope
6156             });
6157         },
6158
6159         // adds a 'sequence' called after the original method
6160         afterMethod : function(method, fn, scope){
6161             getMethodEvent.call(this, method).after.push({
6162                 fn: fn,
6163                 scope: scope
6164             });
6165         },
6166
6167         removeMethodListener: function(method, fn, scope){
6168             var e = this.getMethodEvent(method);
6169             for(var i = 0, len = e.before.length; i < len; i++){
6170                 if(e.before[i].fn == fn && e.before[i].scope == scope){
6171                     e.before.splice(i, 1);
6172                     return;
6173                 }
6174             }
6175             for(var i = 0, len = e.after.length; i < len; i++){
6176                 if(e.after[i].fn == fn && e.after[i].scope == scope){
6177                     e.after.splice(i, 1);
6178                     return;
6179                 }
6180             }
6181         },
6182
6183         /**
6184          * Relays selected events from the specified Observable as if the events were fired by <tt><b>this</b></tt>.
6185          * @param {Object} o The Observable whose events this object is to relay.
6186          * @param {Array} events Array of event names to relay.
6187          */
6188         relayEvents : function(o, events){
6189             var me = this;
6190             function createHandler(ename){
6191                 return function(){
6192                     return me.fireEvent.apply(me, [ename].concat(Array.prototype.slice.call(arguments, 0)));
6193                 };
6194             }
6195             for(var i = 0, len = events.length; i < len; i++){
6196                 var ename = events[i];
6197                 me.events[ename] = me.events[ename] || true;
6198                 o.on(ename, createHandler(ename), me);
6199             }
6200         },
6201
6202         /**
6203          * <p>Enables events fired by this Observable to bubble up an owner hierarchy by calling
6204          * <code>this.getBubbleTarget()</code> if present. There is no implementation in the Observable base class.</p>
6205          * <p>This is commonly used by Ext.Components to bubble events to owner Containers. See {@link Ext.Component.getBubbleTarget}. The default
6206          * implementation in Ext.Component returns the Component's immediate owner. But if a known target is required, this can be overridden to
6207          * access the required target more quickly.</p>
6208          * <p>Example:</p><pre><code>
6209 Ext.override(Ext.form.Field, {
6210     
6211     initComponent : Ext.form.Field.prototype.initComponent.createSequence(function() {
6212         this.enableBubble('change');
6213     }),
6214
6215     
6216     getBubbleTarget : function() {
6217         if (!this.formPanel) {
6218             this.formPanel = this.findParentByType('form');
6219         }
6220         return this.formPanel;
6221     }
6222 });
6223
6224 var myForm = new Ext.formPanel({
6225     title: 'User Details',
6226     items: [{
6227         ...
6228     }],
6229     listeners: {
6230         change: function() {
6231             
6232             myForm.header.setStyle('color', 'red');
6233         }
6234     }
6235 });
6236 </code></pre>
6237          * @param {String/Array} events The event name to bubble, or an Array of event names.
6238          */
6239         enableBubble : function(events){
6240             var me = this;
6241             if(!Ext.isEmpty(events)){
6242                 events = Ext.isArray(events) ? events : Array.prototype.slice.call(arguments, 0);
6243                 for(var i = 0, len = events.length; i < len; i++){
6244                     var ename = events[i];
6245                     ename = ename.toLowerCase();
6246                     var ce = me.events[ename] || true;
6247                     if (typeof ce == 'boolean') {
6248                         ce = new Ext.util.Event(me, ename);
6249                         me.events[ename] = ce;
6250                     }
6251                     ce.bubble = true;
6252                 }
6253             }
6254         }
6255     };
6256 }());
6257
6258
6259
6260 Ext.util.Observable.capture = function(o, fn, scope){
6261     o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
6262 };
6263
6264
6265
6266 Ext.util.Observable.observeClass = function(c, listeners){
6267     if(c){
6268       if(!c.fireEvent){
6269           Ext.apply(c, new Ext.util.Observable());
6270           Ext.util.Observable.capture(c.prototype, c.fireEvent, c);
6271       }
6272       if(typeof listeners == 'object'){
6273           c.on(listeners);
6274       }
6275       return c;
6276    }
6277 };
6278
6279 Ext.apply(Ext.EventManager, function(){
6280    var resizeEvent,
6281        resizeTask,
6282        textEvent,
6283        textSize,
6284        D = Ext.lib.Dom,
6285        propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
6286        curWidth = 0,
6287        curHeight = 0,
6288        
6289        
6290        
6291        useKeydown = Ext.isWebKit ?
6292                    Ext.num(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1]) >= 525 :
6293                    !((Ext.isGecko && !Ext.isWindows) || Ext.isOpera);
6294
6295    return {
6296        
6297        doResizeEvent: function(){
6298            var h = D.getViewHeight(),
6299                w = D.getViewWidth();
6300
6301             
6302             if(curHeight != h || curWidth != w){
6303                resizeEvent.fire(curWidth = w, curHeight = h);
6304             }
6305        },
6306
6307        
6308        onWindowResize : function(fn, scope, options){
6309            if(!resizeEvent){
6310                resizeEvent = new Ext.util.Event();
6311                resizeTask = new Ext.util.DelayedTask(this.doResizeEvent);
6312                Ext.EventManager.on(window, "resize", this.fireWindowResize, this);
6313            }
6314            resizeEvent.addListener(fn, scope, options);
6315        },
6316
6317        
6318        fireWindowResize : function(){
6319            if(resizeEvent){
6320                resizeTask.delay(100);
6321            }
6322        },
6323
6324        
6325        onTextResize : function(fn, scope, options){
6326            if(!textEvent){
6327                textEvent = new Ext.util.Event();
6328                var textEl = new Ext.Element(document.createElement('div'));
6329                textEl.dom.className = 'x-text-resize';
6330                textEl.dom.innerHTML = 'X';
6331                textEl.appendTo(document.body);
6332                textSize = textEl.dom.offsetHeight;
6333                setInterval(function(){
6334                    if(textEl.dom.offsetHeight != textSize){
6335                        textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6336                    }
6337                }, this.textResizeInterval);
6338            }
6339            textEvent.addListener(fn, scope, options);
6340        },
6341
6342        
6343        removeResizeListener : function(fn, scope){
6344            if(resizeEvent){
6345                resizeEvent.removeListener(fn, scope);
6346            }
6347        },
6348
6349        
6350        fireResize : function(){
6351            if(resizeEvent){
6352                resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6353            }
6354        },
6355
6356         
6357        textResizeInterval : 50,
6358
6359        
6360        ieDeferSrc : false,
6361        
6362        
6363        getKeyEvent : function(){
6364            return useKeydown ? 'keydown' : 'keypress';
6365        },
6366
6367        
6368        
6369        useKeydown: useKeydown
6370    };
6371 }());
6372
6373 Ext.EventManager.on = Ext.EventManager.addListener;
6374
6375
6376 Ext.apply(Ext.EventObjectImpl.prototype, {
6377    
6378    BACKSPACE: 8,
6379    
6380    TAB: 9,
6381    
6382    NUM_CENTER: 12,
6383    
6384    ENTER: 13,
6385    
6386    RETURN: 13,
6387    
6388    SHIFT: 16,
6389    
6390    CTRL: 17,
6391    CONTROL : 17, 
6392    
6393    ALT: 18,
6394    
6395    PAUSE: 19,
6396    
6397    CAPS_LOCK: 20,
6398    
6399    ESC: 27,
6400    
6401    SPACE: 32,
6402    
6403    PAGE_UP: 33,
6404    PAGEUP : 33, 
6405    
6406    PAGE_DOWN: 34,
6407    PAGEDOWN : 34, 
6408    
6409    END: 35,
6410    
6411    HOME: 36,
6412    
6413    LEFT: 37,
6414    
6415    UP: 38,
6416    
6417    RIGHT: 39,
6418    
6419    DOWN: 40,
6420    
6421    PRINT_SCREEN: 44,
6422    
6423    INSERT: 45,
6424    
6425    DELETE: 46,
6426    
6427    ZERO: 48,
6428    
6429    ONE: 49,
6430    
6431    TWO: 50,
6432    
6433    THREE: 51,
6434    
6435    FOUR: 52,
6436    
6437    FIVE: 53,
6438    
6439    SIX: 54,
6440    
6441    SEVEN: 55,
6442    
6443    EIGHT: 56,
6444    
6445    NINE: 57,
6446    
6447    A: 65,
6448    
6449    B: 66,
6450    
6451    C: 67,
6452    
6453    D: 68,
6454    
6455    E: 69,
6456    
6457    F: 70,
6458    
6459    G: 71,
6460    
6461    H: 72,
6462    
6463    I: 73,
6464    
6465    J: 74,
6466    
6467    K: 75,
6468    
6469    L: 76,
6470    
6471    M: 77,
6472    
6473    N: 78,
6474    
6475    O: 79,
6476    
6477    P: 80,
6478    
6479    Q: 81,
6480    
6481    R: 82,
6482    
6483    S: 83,
6484    
6485    T: 84,
6486    
6487    U: 85,
6488    
6489    V: 86,
6490    
6491    W: 87,
6492    
6493    X: 88,
6494    
6495    Y: 89,
6496    
6497    Z: 90,
6498    
6499    CONTEXT_MENU: 93,
6500    
6501    NUM_ZERO: 96,
6502    
6503    NUM_ONE: 97,
6504    
6505    NUM_TWO: 98,
6506    
6507    NUM_THREE: 99,
6508    
6509    NUM_FOUR: 100,
6510    
6511    NUM_FIVE: 101,
6512    
6513    NUM_SIX: 102,
6514    
6515    NUM_SEVEN: 103,
6516    
6517    NUM_EIGHT: 104,
6518    
6519    NUM_NINE: 105,
6520    
6521    NUM_MULTIPLY: 106,
6522    
6523    NUM_PLUS: 107,
6524    
6525    NUM_MINUS: 109,
6526    
6527    NUM_PERIOD: 110,
6528    
6529    NUM_DIVISION: 111,
6530    
6531    F1: 112,
6532    
6533    F2: 113,
6534    
6535    F3: 114,
6536    
6537    F4: 115,
6538    
6539    F5: 116,
6540    
6541    F6: 117,
6542    
6543    F7: 118,
6544    
6545    F8: 119,
6546    
6547    F9: 120,
6548    
6549    F10: 121,
6550    
6551    F11: 122,
6552    
6553    F12: 123,
6554
6555    
6556    isNavKeyPress : function(){
6557        var me = this,
6558            k = this.normalizeKey(me.keyCode);
6559        return (k >= 33 && k <= 40) ||  
6560        k == me.RETURN ||
6561        k == me.TAB ||
6562        k == me.ESC;
6563    },
6564
6565    isSpecialKey : function(){
6566        var k = this.normalizeKey(this.keyCode);
6567        return (this.type == 'keypress' && this.ctrlKey) ||
6568        this.isNavKeyPress() ||
6569        (k == this.BACKSPACE) || 
6570        (k >= 16 && k <= 20) || 
6571        (k >= 44 && k <= 46);   
6572    },
6573
6574    getPoint : function(){
6575        return new Ext.lib.Point(this.xy[0], this.xy[1]);
6576    },
6577
6578    
6579    hasModifier : function(){
6580        return ((this.ctrlKey || this.altKey) || this.shiftKey);
6581    }
6582 });
6583 Ext.Element.addMethods({
6584     
6585     swallowEvent : function(eventName, preventDefault) {
6586         var me = this;
6587         function fn(e) {
6588             e.stopPropagation();
6589             if (preventDefault) {
6590                 e.preventDefault();
6591             }
6592         }
6593         
6594         if (Ext.isArray(eventName)) {
6595             Ext.each(eventName, function(e) {
6596                  me.on(e, fn);
6597             });
6598             return me;
6599         }
6600         me.on(eventName, fn);
6601         return me;
6602     },
6603
6604     
6605     relayEvent : function(eventName, observable) {
6606         this.on(eventName, function(e) {
6607             observable.fireEvent(eventName, e);
6608         });
6609     },
6610
6611     
6612     clean : function(forceReclean) {
6613         var me  = this,
6614             dom = me.dom,
6615             n   = dom.firstChild,
6616             ni  = -1;
6617
6618         if (Ext.Element.data(dom, 'isCleaned') && forceReclean !== true) {
6619             return me;
6620         }
6621
6622         while (n) {
6623             var nx = n.nextSibling;
6624             if (n.nodeType == 3 && !(/\S/.test(n.nodeValue))) {
6625                 dom.removeChild(n);
6626             } else {
6627                 n.nodeIndex = ++ni;
6628             }
6629             n = nx;
6630         }
6631         
6632         Ext.Element.data(dom, 'isCleaned', true);
6633         return me;
6634     },
6635
6636     
6637     load : function() {
6638         var updateManager = this.getUpdater();
6639         updateManager.update.apply(updateManager, arguments);
6640         
6641         return this;
6642     },
6643
6644     
6645     getUpdater : function() {
6646         return this.updateManager || (this.updateManager = new Ext.Updater(this));
6647     },
6648
6649     
6650     update : function(html, loadScripts, callback) {
6651         if (!this.dom) {
6652             return this;
6653         }
6654         html = html || "";
6655
6656         if (loadScripts !== true) {
6657             this.dom.innerHTML = html;
6658             if (typeof callback == 'function') {
6659                 callback();
6660             }
6661             return this;
6662         }
6663
6664         var id  = Ext.id(),
6665             dom = this.dom;
6666
6667         html += '<span id="' + id + '"></span>';
6668
6669         Ext.lib.Event.onAvailable(id, function() {
6670             var DOC    = document,
6671                 hd     = DOC.getElementsByTagName("head")[0],
6672                 re     = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,
6673                 srcRe  = /\ssrc=([\'\"])(.*?)\1/i,
6674                 typeRe = /\stype=([\'\"])(.*?)\1/i,
6675                 match,
6676                 attrs,
6677                 srcMatch,
6678                 typeMatch,
6679                 el,
6680                 s;
6681
6682             while ((match = re.exec(html))) {
6683                 attrs = match[1];
6684                 srcMatch = attrs ? attrs.match(srcRe) : false;
6685                 if (srcMatch && srcMatch[2]) {
6686                    s = DOC.createElement("script");
6687                    s.src = srcMatch[2];
6688                    typeMatch = attrs.match(typeRe);
6689                    if (typeMatch && typeMatch[2]) {
6690                        s.type = typeMatch[2];
6691                    }
6692                    hd.appendChild(s);
6693                 } else if (match[2] && match[2].length > 0) {
6694                     if (window.execScript) {
6695                        window.execScript(match[2]);
6696                     } else {
6697                        window.eval(match[2]);
6698                     }
6699                 }
6700             }
6701             
6702             el = DOC.getElementById(id);
6703             if (el) {
6704                 Ext.removeNode(el);
6705             }
6706             
6707             if (typeof callback == 'function') {
6708                 callback();
6709             }
6710         });
6711         dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
6712         return this;
6713     },
6714
6715     
6716     removeAllListeners : function() {
6717         this.removeAnchor();
6718         Ext.EventManager.removeAll(this.dom);
6719         return this;
6720     },
6721
6722     
6723     createProxy : function(config, renderTo, matchBox) {
6724         config = (typeof config == 'object') ? config : {tag : "div", cls: config};
6725
6726         var me = this,
6727             proxy = renderTo ? Ext.DomHelper.append(renderTo, config, true) :
6728                                Ext.DomHelper.insertBefore(me.dom, config, true);
6729
6730         if (matchBox && me.setBox && me.getBox) { 
6731            proxy.setBox(me.getBox());
6732         }
6733         return proxy;
6734     }
6735 });
6736
6737 Ext.Element.prototype.getUpdateManager = Ext.Element.prototype.getUpdater;
6738
6739 Ext.Element.addMethods({
6740     
6741     getAnchorXY : function(anchor, local, s){
6742         
6743         
6744                 anchor = (anchor || "tl").toLowerCase();
6745         s = s || {};
6746         
6747         var me = this,        
6748                 vp = me.dom == document.body || me.dom == document,
6749                 w = s.width || vp ? Ext.lib.Dom.getViewWidth() : me.getWidth(),
6750                 h = s.height || vp ? Ext.lib.Dom.getViewHeight() : me.getHeight(),                              
6751                 xy,             
6752                 r = Math.round,
6753                 o = me.getXY(),
6754                 scroll = me.getScroll(),
6755                 extraX = vp ? scroll.left : !local ? o[0] : 0,
6756                 extraY = vp ? scroll.top : !local ? o[1] : 0,
6757                 hash = {
6758                         c  : [r(w * 0.5), r(h * 0.5)],
6759                         t  : [r(w * 0.5), 0],
6760                         l  : [0, r(h * 0.5)],
6761                         r  : [w, r(h * 0.5)],
6762                         b  : [r(w * 0.5), h],
6763                         tl : [0, 0],    
6764                         bl : [0, h],
6765                         br : [w, h],
6766                         tr : [w, 0]
6767                 };
6768         
6769         xy = hash[anchor];      
6770         return [xy[0] + extraX, xy[1] + extraY]; 
6771     },
6772
6773     
6774     anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){        
6775             var me = this,
6776             dom = me.dom,
6777             scroll = !Ext.isEmpty(monitorScroll),
6778             action = function(){
6779                 Ext.fly(dom).alignTo(el, alignment, offsets, animate);
6780                 Ext.callback(callback, Ext.fly(dom));
6781             },
6782             anchor = this.getAnchor();
6783             
6784         
6785         this.removeAnchor();
6786         Ext.apply(anchor, {
6787             fn: action,
6788             scroll: scroll
6789         });
6790
6791         Ext.EventManager.onWindowResize(action, null);
6792         
6793         if(scroll){
6794             Ext.EventManager.on(window, 'scroll', action, null,
6795                 {buffer: !isNaN(monitorScroll) ? monitorScroll : 50});
6796         }
6797         action.call(me); 
6798         return me;
6799     },
6800     
6801     
6802     removeAnchor : function(){
6803         var me = this,
6804             anchor = this.getAnchor();
6805             
6806         if(anchor && anchor.fn){
6807             Ext.EventManager.removeResizeListener(anchor.fn);
6808             if(anchor.scroll){
6809                 Ext.EventManager.un(window, 'scroll', anchor.fn);
6810             }
6811             delete anchor.fn;
6812         }
6813         return me;
6814     },
6815     
6816     
6817     getAnchor : function(){
6818         var data = Ext.Element.data,
6819             dom = this.dom;
6820             if (!dom) {
6821                 return;
6822             }
6823             var anchor = data(dom, '_anchor');
6824             
6825         if(!anchor){
6826             anchor = data(dom, '_anchor', {});
6827         }
6828         return anchor;
6829     },
6830
6831     
6832     getAlignToXY : function(el, p, o){      
6833         el = Ext.get(el);
6834         
6835         if(!el || !el.dom){
6836             throw "Element.alignToXY with an element that doesn't exist";
6837         }
6838         
6839         o = o || [0,0];
6840         p = (!p || p == "?" ? "tl-bl?" : (!(/-/).test(p) && p !== "" ? "tl-" + p : p || "tl-bl")).toLowerCase();       
6841                 
6842         var me = this,
6843                 d = me.dom,
6844                 a1,
6845                 a2,
6846                 x,
6847                 y,
6848                 
6849                 w,
6850                 h,
6851                 r,
6852                 dw = Ext.lib.Dom.getViewWidth() -10, 
6853                 dh = Ext.lib.Dom.getViewHeight()-10, 
6854                 p1y,
6855                 p1x,            
6856                 p2y,
6857                 p2x,
6858                 swapY,
6859                 swapX,
6860                 doc = document,
6861                 docElement = doc.documentElement,
6862                 docBody = doc.body,
6863                 scrollX = (docElement.scrollLeft || docBody.scrollLeft || 0)+5,
6864                 scrollY = (docElement.scrollTop || docBody.scrollTop || 0)+5,
6865                 c = false, 
6866                 p1 = "", 
6867                 p2 = "",
6868                 m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
6869         
6870         if(!m){
6871            throw "Element.alignTo with an invalid alignment " + p;
6872         }
6873         
6874         p1 = m[1]; 
6875         p2 = m[2]; 
6876         c = !!m[3];
6877
6878         
6879         
6880         a1 = me.getAnchorXY(p1, true);
6881         a2 = el.getAnchorXY(p2, false);
6882
6883         x = a2[0] - a1[0] + o[0];
6884         y = a2[1] - a1[1] + o[1];
6885
6886         if(c){    
6887                w = me.getWidth();
6888            h = me.getHeight();
6889            r = el.getRegion();       
6890            
6891            
6892            
6893            p1y = p1.charAt(0);
6894            p1x = p1.charAt(p1.length-1);
6895            p2y = p2.charAt(0);
6896            p2x = p2.charAt(p2.length-1);
6897            swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
6898            swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));          
6899            
6900
6901            if (x + w > dw + scrollX) {
6902                 x = swapX ? r.left-w : dw+scrollX-w;
6903            }
6904            if (x < scrollX) {
6905                x = swapX ? r.right : scrollX;
6906            }
6907            if (y + h > dh + scrollY) {
6908                 y = swapY ? r.top-h : dh+scrollY-h;
6909             }
6910            if (y < scrollY){
6911                y = swapY ? r.bottom : scrollY;
6912            }
6913         }
6914         return [x,y];
6915     },
6916
6917     
6918     alignTo : function(element, position, offsets, animate){
6919             var me = this;
6920         return me.setXY(me.getAlignToXY(element, position, offsets),
6921                                 me.preanim && !!animate ? me.preanim(arguments, 3) : false);
6922     },
6923     
6924     
6925     adjustForConstraints : function(xy, parent, offsets){
6926         return this.getConstrainToXY(parent || document, false, offsets, xy) ||  xy;
6927     },
6928
6929     
6930     getConstrainToXY : function(el, local, offsets, proposedXY){   
6931             var os = {top:0, left:0, bottom:0, right: 0};
6932
6933         return function(el, local, offsets, proposedXY){
6934             el = Ext.get(el);
6935             offsets = offsets ? Ext.applyIf(offsets, os) : os;
6936
6937             var vw, vh, vx = 0, vy = 0;
6938             if(el.dom == document.body || el.dom == document){
6939                 vw =Ext.lib.Dom.getViewWidth();
6940                 vh = Ext.lib.Dom.getViewHeight();
6941             }else{
6942                 vw = el.dom.clientWidth;
6943                 vh = el.dom.clientHeight;
6944                 if(!local){
6945                     var vxy = el.getXY();
6946                     vx = vxy[0];
6947                     vy = vxy[1];
6948                 }
6949             }
6950
6951             var s = el.getScroll();
6952
6953             vx += offsets.left + s.left;
6954             vy += offsets.top + s.top;
6955
6956             vw -= offsets.right;
6957             vh -= offsets.bottom;
6958
6959             var vr = vx + vw,
6960                 vb = vy + vh,
6961                 xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]),
6962                 x = xy[0], y = xy[1],
6963                 offset = this.getConstrainOffset(),
6964                 w = this.dom.offsetWidth + offset, 
6965                 h = this.dom.offsetHeight + offset;
6966
6967             
6968             var moved = false;
6969
6970             
6971             if((x + w) > vr){
6972                 x = vr - w;
6973                 moved = true;
6974             }
6975             if((y + h) > vb){
6976                 y = vb - h;
6977                 moved = true;
6978             }
6979             
6980             if(x < vx){
6981                 x = vx;
6982                 moved = true;
6983             }
6984             if(y < vy){
6985                 y = vy;
6986                 moved = true;
6987             }
6988             return moved ? [x, y] : false;
6989         };
6990     }(),
6991             
6992             
6993                 
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045
7046
7047     
7048     getConstrainOffset : function(){
7049         return 0;
7050     },
7051     
7052     
7053     getCenterXY : function(){
7054         return this.getAlignToXY(document, 'c-c');
7055     },
7056
7057     
7058     center : function(centerIn){
7059         return this.alignTo(centerIn || document, 'c-c');        
7060     }    
7061 });
7062
7063 Ext.Element.addMethods({
7064     
7065     select : function(selector, unique){
7066         return Ext.Element.select(selector, unique, this.dom);
7067     }
7068 });
7069 Ext.apply(Ext.Element.prototype, function() {
7070         var GETDOM = Ext.getDom,
7071                 GET = Ext.get,
7072                 DH = Ext.DomHelper;
7073         
7074         return {        
7075                 
7076             insertSibling: function(el, where, returnDom){
7077                 var me = this,
7078                         rt,
7079                 isAfter = (where || 'before').toLowerCase() == 'after',
7080                 insertEl;
7081                         
7082                 if(Ext.isArray(el)){
7083                 insertEl = me;
7084                     Ext.each(el, function(e) {
7085                             rt = Ext.fly(insertEl, '_internal').insertSibling(e, where, returnDom);
7086                     if(isAfter){
7087                         insertEl = rt;
7088                     }
7089                     });
7090                     return rt;
7091                 }
7092                         
7093                 el = el || {};
7094                 
7095             if(el.nodeType || el.dom){
7096                 rt = me.dom.parentNode.insertBefore(GETDOM(el), isAfter ? me.dom.nextSibling : me.dom);
7097                 if (!returnDom) {
7098                     rt = GET(rt);
7099                 }
7100             }else{
7101                 if (isAfter && !me.dom.nextSibling) {
7102                     rt = DH.append(me.dom.parentNode, el, !returnDom);
7103                 } else {                    
7104                     rt = DH[isAfter ? 'insertAfter' : 'insertBefore'](me.dom, el, !returnDom);
7105                 }
7106             }
7107                 return rt;
7108             }
7109     };
7110 }());
7111
7112
7113 Ext.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>';
7114
7115 Ext.Element.addMethods(function(){
7116     var INTERNAL = "_internal",
7117         pxMatch = /(\d+\.?\d+)px/;
7118     return {
7119         
7120         applyStyles : function(style){
7121             Ext.DomHelper.applyStyles(this.dom, style);
7122             return this;
7123         },
7124
7125         
7126         getStyles : function(){
7127             var ret = {};
7128             Ext.each(arguments, function(v) {
7129                ret[v] = this.getStyle(v);
7130             },
7131             this);
7132             return ret;
7133         },
7134
7135         
7136         setOverflow : function(v){
7137             var dom = this.dom;
7138             if(v=='auto' && Ext.isMac && Ext.isGecko2){ 
7139                 dom.style.overflow = 'hidden';
7140                 (function(){dom.style.overflow = 'auto';}).defer(1);
7141             }else{
7142                 dom.style.overflow = v;
7143             }
7144         },
7145
7146        
7147         boxWrap : function(cls){
7148             cls = cls || 'x-box';
7149             var el = Ext.get(this.insertHtml("beforeBegin", "<div class='" + cls + "'>" + String.format(Ext.Element.boxMarkup, cls) + "</div>"));        
7150             Ext.DomQuery.selectNode('.' + cls + '-mc', el.dom).appendChild(this.dom);
7151             return el;
7152         },
7153
7154         
7155         setSize : function(width, height, animate){
7156             var me = this;
7157             if(typeof width == 'object'){ 
7158                 height = width.height;
7159                 width = width.width;
7160             }
7161             width = me.adjustWidth(width);
7162             height = me.adjustHeight(height);
7163             if(!animate || !me.anim){
7164                 me.dom.style.width = me.addUnits(width);
7165                 me.dom.style.height = me.addUnits(height);
7166             }else{
7167                 me.anim({width: {to: width}, height: {to: height}}, me.preanim(arguments, 2));
7168             }
7169             return me;
7170         },
7171
7172         
7173         getComputedHeight : function(){
7174             var me = this,
7175                 h = Math.max(me.dom.offsetHeight, me.dom.clientHeight);
7176             if(!h){
7177                 h = parseFloat(me.getStyle('height')) || 0;
7178                 if(!me.isBorderBox()){
7179                     h += me.getFrameWidth('tb');
7180                 }
7181             }
7182             return h;
7183         },
7184
7185         
7186         getComputedWidth : function(){
7187             var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7188             if(!w){
7189                 w = parseFloat(this.getStyle('width')) || 0;
7190                 if(!this.isBorderBox()){
7191                     w += this.getFrameWidth('lr');
7192                 }
7193             }
7194             return w;
7195         },
7196
7197         
7198         getFrameWidth : function(sides, onlyContentBox){
7199             return onlyContentBox && this.isBorderBox() ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
7200         },
7201
7202         
7203         addClassOnOver : function(className){
7204             this.hover(
7205                 function(){
7206                     Ext.fly(this, INTERNAL).addClass(className);
7207                 },
7208                 function(){
7209                     Ext.fly(this, INTERNAL).removeClass(className);
7210                 }
7211             );
7212             return this;
7213         },
7214
7215         
7216         addClassOnFocus : function(className){
7217             this.on("focus", function(){
7218                 Ext.fly(this, INTERNAL).addClass(className);
7219             }, this.dom);
7220             this.on("blur", function(){
7221                 Ext.fly(this, INTERNAL).removeClass(className);
7222             }, this.dom);
7223             return this;
7224         },
7225
7226         
7227         addClassOnClick : function(className){
7228             var dom = this.dom;
7229             this.on("mousedown", function(){
7230                 Ext.fly(dom, INTERNAL).addClass(className);
7231                 var d = Ext.getDoc(),
7232                     fn = function(){
7233                         Ext.fly(dom, INTERNAL).removeClass(className);
7234                         d.removeListener("mouseup", fn);
7235                     };
7236                 d.on("mouseup", fn);
7237             });
7238             return this;
7239         },
7240
7241         
7242
7243         getViewSize : function(){
7244             var doc = document,
7245                 d = this.dom,
7246                 isDoc = (d == doc || d == doc.body);
7247
7248             
7249             if (isDoc) {
7250                 var extdom = Ext.lib.Dom;
7251                 return {
7252                     width : extdom.getViewWidth(),
7253                     height : extdom.getViewHeight()
7254                 };
7255
7256             
7257             } else {
7258                 return {
7259                     width : d.clientWidth,
7260                     height : d.clientHeight
7261                 };
7262             }
7263         },
7264
7265         
7266
7267         getStyleSize : function(){
7268             var me = this,
7269                 w, h,
7270                 doc = document,
7271                 d = this.dom,
7272                 isDoc = (d == doc || d == doc.body),
7273                 s = d.style;
7274
7275             
7276             if (isDoc) {
7277                 var extdom = Ext.lib.Dom;
7278                 return {
7279                     width : extdom.getViewWidth(),
7280                     height : extdom.getViewHeight()
7281                 };
7282             }
7283             
7284             if(s.width && s.width != 'auto'){
7285                 w = parseFloat(s.width);
7286                 if(me.isBorderBox()){
7287                    w -= me.getFrameWidth('lr');
7288                 }
7289             }
7290             
7291             if(s.height && s.height != 'auto'){
7292                 h = parseFloat(s.height);
7293                 if(me.isBorderBox()){
7294                    h -= me.getFrameWidth('tb');
7295                 }
7296             }
7297             
7298             return {width: w || me.getWidth(true), height: h || me.getHeight(true)};
7299         },
7300
7301         
7302         getSize : function(contentSize){
7303             return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7304         },
7305
7306         
7307         repaint : function(){
7308             var dom = this.dom;
7309             this.addClass("x-repaint");
7310             setTimeout(function(){
7311                 Ext.fly(dom).removeClass("x-repaint");
7312             }, 1);
7313             return this;
7314         },
7315
7316         
7317         unselectable : function(){
7318             this.dom.unselectable = "on";
7319             return this.swallowEvent("selectstart", true).
7320                         applyStyles("-moz-user-select:none;-khtml-user-select:none;").
7321                         addClass("x-unselectable");
7322         },
7323
7324         
7325         getMargins : function(side){
7326             var me = this,
7327                 key,
7328                 hash = {t:"top", l:"left", r:"right", b: "bottom"},
7329                 o = {};
7330
7331             if (!side) {
7332                 for (key in me.margins){
7333                     o[hash[key]] = parseFloat(me.getStyle(me.margins[key])) || 0;
7334                 }
7335                 return o;
7336             } else {
7337                 return me.addStyles.call(me, side, me.margins);
7338             }
7339         }
7340     };
7341 }());
7342
7343 Ext.Element.addMethods({
7344     
7345     setBox : function(box, adjust, animate){
7346         var me = this,
7347                 w = box.width, 
7348                 h = box.height;
7349         if((adjust && !me.autoBoxAdjust) && !me.isBorderBox()){
7350            w -= (me.getBorderWidth("lr") + me.getPadding("lr"));
7351            h -= (me.getBorderWidth("tb") + me.getPadding("tb"));
7352         }
7353         me.setBounds(box.x, box.y, w, h, me.animTest.call(me, arguments, animate, 2));
7354         return me;
7355     },
7356
7357     
7358         getBox : function(contentBox, local) {      
7359             var me = this,
7360                 xy,
7361                 left,
7362                 top,
7363                 getBorderWidth = me.getBorderWidth,
7364                 getPadding = me.getPadding, 
7365                 l,
7366                 r,
7367                 t,
7368                 b;
7369         if(!local){
7370             xy = me.getXY();
7371         }else{
7372             left = parseInt(me.getStyle("left"), 10) || 0;
7373             top = parseInt(me.getStyle("top"), 10) || 0;
7374             xy = [left, top];
7375         }
7376         var el = me.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
7377         if(!contentBox){
7378             bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
7379         }else{
7380             l = getBorderWidth.call(me, "l") + getPadding.call(me, "l");
7381             r = getBorderWidth.call(me, "r") + getPadding.call(me, "r");
7382             t = getBorderWidth.call(me, "t") + getPadding.call(me, "t");
7383             b = getBorderWidth.call(me, "b") + getPadding.call(me, "b");
7384             bx = {x: xy[0]+l, y: xy[1]+t, 0: xy[0]+l, 1: xy[1]+t, width: w-(l+r), height: h-(t+b)};
7385         }
7386         bx.right = bx.x + bx.width;
7387         bx.bottom = bx.y + bx.height;
7388         return bx;
7389         },
7390         
7391     
7392      move : function(direction, distance, animate){
7393         var me = this,          
7394                 xy = me.getXY(),
7395                 x = xy[0],
7396                 y = xy[1],              
7397                 left = [x - distance, y],
7398                 right = [x + distance, y],
7399                 top = [x, y - distance],
7400                 bottom = [x, y + distance],
7401                 hash = {
7402                         l :     left,
7403                         left : left,
7404                         r : right,
7405                         right : right,
7406                         t : top,
7407                         top : top,
7408                         up : top,
7409                         b : bottom, 
7410                         bottom : bottom,
7411                         down : bottom                           
7412                 };
7413         
7414             direction = direction.toLowerCase();    
7415             me.moveTo(hash[direction][0], hash[direction][1], me.animTest.call(me, arguments, animate, 2));
7416     },
7417     
7418     
7419      setLeftTop : function(left, top){
7420             var me = this,
7421                 style = me.dom.style;
7422         style.left = me.addUnits(left);
7423         style.top = me.addUnits(top);
7424         return me;
7425     },
7426     
7427     
7428     getRegion : function(){
7429         return Ext.lib.Dom.getRegion(this.dom);
7430     },
7431     
7432     
7433     setBounds : function(x, y, width, height, animate){
7434             var me = this;
7435         if (!animate || !me.anim) {
7436             me.setSize(width, height);
7437             me.setLocation(x, y);
7438         } else {
7439             me.anim({points: {to: [x, y]}, 
7440                          width: {to: me.adjustWidth(width)}, 
7441                          height: {to: me.adjustHeight(height)}},
7442                      me.preanim(arguments, 4), 
7443                      'motion');
7444         }
7445         return me;
7446     },
7447
7448     
7449     setRegion : function(region, animate) {
7450         return this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.animTest.call(this, arguments, animate, 1));
7451     }
7452 });
7453 Ext.Element.addMethods({
7454     
7455     scrollTo : function(side, value, animate) {
7456         
7457         var top = /top/i.test(side),
7458             me = this,
7459             dom = me.dom,
7460             prop;
7461         if (!animate || !me.anim) {
7462             
7463             prop = 'scroll' + (top ? 'Top' : 'Left');
7464             dom[prop] = value;
7465         }
7466         else {
7467             
7468             prop = 'scroll' + (top ? 'Left' : 'Top');
7469             me.anim({scroll: {to: top ? [dom[prop], value] : [value, dom[prop]]}}, me.preanim(arguments, 2), 'scroll');
7470         }
7471         return me;
7472     },
7473     
7474     
7475     scrollIntoView : function(container, hscroll) {
7476         var c = Ext.getDom(container) || Ext.getBody().dom,
7477             el = this.dom,
7478             o = this.getOffsetsTo(c),
7479             l = o[0] + c.scrollLeft,
7480             t = o[1] + c.scrollTop,
7481             b = t + el.offsetHeight,
7482             r = l + el.offsetWidth,
7483             ch = c.clientHeight,
7484             ct = parseInt(c.scrollTop, 10),
7485             cl = parseInt(c.scrollLeft, 10),
7486             cb = ct + ch,
7487             cr = cl + c.clientWidth;
7488
7489         if (el.offsetHeight > ch || t < ct) {
7490             c.scrollTop = t;
7491         }
7492         else if (b > cb) {
7493             c.scrollTop = b-ch;
7494         }
7495         
7496         c.scrollTop = c.scrollTop;
7497
7498         if (hscroll !== false) {
7499             if (el.offsetWidth > c.clientWidth || l < cl) {
7500                 c.scrollLeft = l;
7501             }
7502             else if (r > cr) {
7503                 c.scrollLeft = r - c.clientWidth;
7504             }
7505             c.scrollLeft = c.scrollLeft;
7506         }
7507         return this;
7508     },
7509
7510     
7511     scrollChildIntoView : function(child, hscroll) {
7512         Ext.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
7513     },
7514     
7515     
7516      scroll : function(direction, distance, animate) {
7517         if (!this.isScrollable()) {
7518             return false;
7519         }
7520         var el = this.dom,
7521             l = el.scrollLeft, t = el.scrollTop,
7522             w = el.scrollWidth, h = el.scrollHeight,
7523             cw = el.clientWidth, ch = el.clientHeight,
7524             scrolled = false, v,
7525             hash = {
7526                 l: Math.min(l + distance, w-cw),
7527                 r: v = Math.max(l - distance, 0),
7528                 t: Math.max(t - distance, 0),
7529                 b: Math.min(t + distance, h-ch)
7530             };
7531             hash.d = hash.b;
7532             hash.u = hash.t;
7533         
7534         direction = direction.substr(0, 1);
7535         if ((v = hash[direction]) > -1) {
7536             scrolled = true;
7537             this.scrollTo(direction == 'l' || direction == 'r' ? 'left' : 'top', v, this.preanim(arguments, 2));
7538         }
7539         return scrolled;
7540     }
7541 });
7542 Ext.Element.addMethods(
7543     function() {
7544         var VISIBILITY      = "visibility",
7545             DISPLAY         = "display",
7546             HIDDEN          = "hidden",
7547             NONE            = "none",
7548             XMASKED         = "x-masked",
7549             XMASKEDRELATIVE = "x-masked-relative",
7550             data            = Ext.Element.data;
7551
7552         return {
7553             
7554             isVisible : function(deep) {
7555                 var vis = !this.isStyle(VISIBILITY, HIDDEN) && !this.isStyle(DISPLAY, NONE),
7556                     p   = this.dom.parentNode;
7557                 
7558                 if (deep !== true || !vis) {
7559                     return vis;
7560                 }
7561                 
7562                 while (p && !(/^body/i.test(p.tagName))) {
7563                     if (!Ext.fly(p, '_isVisible').isVisible()) {
7564                         return false;
7565                     }
7566                     p = p.parentNode;
7567                 }
7568                 return true;
7569             },
7570
7571             
7572             isDisplayed : function() {
7573                 return !this.isStyle(DISPLAY, NONE);
7574             },
7575
7576             
7577             enableDisplayMode : function(display) {
7578                 this.setVisibilityMode(Ext.Element.DISPLAY);
7579                 
7580                 if (!Ext.isEmpty(display)) {
7581                     data(this.dom, 'originalDisplay', display);
7582                 }
7583                 
7584                 return this;
7585             },
7586
7587             
7588             mask : function(msg, msgCls) {
7589                 var me  = this,
7590                     dom = me.dom,
7591                     dh  = Ext.DomHelper,
7592                     EXTELMASKMSG = "ext-el-mask-msg",
7593                     el,
7594                     mask;
7595
7596                 if (!(/^body/i.test(dom.tagName) && me.getStyle('position') == 'static')) {
7597                     me.addClass(XMASKEDRELATIVE);
7598                 }
7599                 if (el = data(dom, 'maskMsg')) {
7600                     el.remove();
7601                 }
7602                 if (el = data(dom, 'mask')) {
7603                     el.remove();
7604                 }
7605
7606                 mask = dh.append(dom, {cls : "ext-el-mask"}, true);
7607                 data(dom, 'mask', mask);
7608
7609                 me.addClass(XMASKED);
7610                 mask.setDisplayed(true);
7611                 
7612                 if (typeof msg == 'string') {
7613                     var mm = dh.append(dom, {cls : EXTELMASKMSG, cn:{tag:'div'}}, true);
7614                     data(dom, 'maskMsg', mm);
7615                     mm.dom.className = msgCls ? EXTELMASKMSG + " " + msgCls : EXTELMASKMSG;
7616                     mm.dom.firstChild.innerHTML = msg;
7617                     mm.setDisplayed(true);
7618                     mm.center(me);
7619                 }
7620                 
7621                 
7622                 if (Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && me.getStyle('height') == 'auto') {
7623                     mask.setSize(undefined, me.getHeight());
7624                 }
7625                 
7626                 return mask;
7627             },
7628
7629             
7630             unmask : function() {
7631                 var me      = this,
7632                     dom     = me.dom,
7633                     mask    = data(dom, 'mask'),
7634                     maskMsg = data(dom, 'maskMsg');
7635
7636                 if (mask) {
7637                     if (maskMsg) {
7638                         maskMsg.remove();
7639                         data(dom, 'maskMsg', undefined);
7640                     }
7641                     
7642                     mask.remove();
7643                     data(dom, 'mask', undefined);
7644                     me.removeClass([XMASKED, XMASKEDRELATIVE]);
7645                 }
7646             },
7647
7648             
7649             isMasked : function() {
7650                 var m = data(this.dom, 'mask');
7651                 return m && m.isVisible();
7652             },
7653
7654             
7655             createShim : function() {
7656                 var el = document.createElement('iframe'),
7657                     shim;
7658                 
7659                 el.frameBorder = '0';
7660                 el.className = 'ext-shim';
7661                 el.src = Ext.SSL_SECURE_URL;
7662                 shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
7663                 shim.autoBoxAdjust = false;
7664                 return shim;
7665             }
7666         };
7667     }()
7668 );
7669 Ext.Element.addMethods({
7670     
7671     addKeyListener : function(key, fn, scope){
7672         var config;
7673         if(typeof key != 'object' || Ext.isArray(key)){
7674             config = {
7675                 key: key,
7676                 fn: fn,
7677                 scope: scope
7678             };
7679         }else{
7680             config = {
7681                 key : key.key,
7682                 shift : key.shift,
7683                 ctrl : key.ctrl,
7684                 alt : key.alt,
7685                 fn: fn,
7686                 scope: scope
7687             };
7688         }
7689         return new Ext.KeyMap(this, config);
7690     },
7691
7692     
7693     addKeyMap : function(config){
7694         return new Ext.KeyMap(this, config);
7695     }
7696 });
7697
7698
7699
7700 Ext.CompositeElementLite.importElementMethods();
7701 Ext.apply(Ext.CompositeElementLite.prototype, {
7702     addElements : function(els, root){
7703         if(!els){
7704             return this;
7705         }
7706         if(typeof els == "string"){
7707             els = Ext.Element.selectorFunction(els, root);
7708         }
7709         var yels = this.elements;
7710         Ext.each(els, function(e) {
7711             yels.push(Ext.get(e));
7712         });
7713         return this;
7714     },
7715
7716     
7717     first : function(){
7718         return this.item(0);
7719     },
7720
7721     
7722     last : function(){
7723         return this.item(this.getCount()-1);
7724     },
7725
7726     
7727     contains : function(el){
7728         return this.indexOf(el) != -1;
7729     },
7730
7731     
7732     removeElement : function(keys, removeDom){
7733         var me = this,
7734             els = this.elements,
7735             el;
7736         Ext.each(keys, function(val){
7737             if ((el = (els[val] || els[val = me.indexOf(val)]))) {
7738                 if(removeDom){
7739                     if(el.dom){
7740                         el.remove();
7741                     }else{
7742                         Ext.removeNode(el);
7743                     }
7744                 }
7745                 els.splice(val, 1);
7746             }
7747         });
7748         return this;
7749     }
7750 });
7751
7752 Ext.CompositeElement = Ext.extend(Ext.CompositeElementLite, {
7753     
7754     constructor : function(els, root){
7755         this.elements = [];
7756         this.add(els, root);
7757     },
7758     
7759     
7760     getElement : function(el){
7761         
7762         return el;
7763     },
7764     
7765     
7766     transformElement : function(el){
7767         return Ext.get(el);
7768     }
7769
7770     
7771
7772     
7773
7774     
7775 });
7776
7777
7778 Ext.Element.select = function(selector, unique, root){
7779     var els;
7780     if(typeof selector == "string"){
7781         els = Ext.Element.selectorFunction(selector, root);
7782     }else if(selector.length !== undefined){
7783         els = selector;
7784     }else{
7785         throw "Invalid selector";
7786     }
7787
7788     return (unique === true) ? new Ext.CompositeElement(els) : new Ext.CompositeElementLite(els);
7789 };
7790
7791
7792 Ext.select = Ext.Element.select;
7793 Ext.UpdateManager = Ext.Updater = Ext.extend(Ext.util.Observable,
7794 function() {
7795     var BEFOREUPDATE = "beforeupdate",
7796         UPDATE = "update",
7797         FAILURE = "failure";
7798
7799     
7800     function processSuccess(response){
7801         var me = this;
7802         me.transaction = null;
7803         if (response.argument.form && response.argument.reset) {
7804             try { 
7805                 response.argument.form.reset();
7806             } catch(e){}
7807         }
7808         if (me.loadScripts) {
7809             me.renderer.render(me.el, response, me,
7810                updateComplete.createDelegate(me, [response]));
7811         } else {
7812             me.renderer.render(me.el, response, me);
7813             updateComplete.call(me, response);
7814         }
7815     }
7816
7817     
7818     function updateComplete(response, type, success){
7819         this.fireEvent(type || UPDATE, this.el, response);
7820         if(Ext.isFunction(response.argument.callback)){
7821             response.argument.callback.call(response.argument.scope, this.el, Ext.isEmpty(success) ? true : false, response, response.argument.options);
7822         }
7823     }
7824
7825     
7826     function processFailure(response){
7827         updateComplete.call(this, response, FAILURE, !!(this.transaction = null));
7828     }
7829
7830     return {
7831         constructor: function(el, forceNew){
7832             var me = this;
7833             el = Ext.get(el);
7834             if(!forceNew && el.updateManager){
7835                 return el.updateManager;
7836             }
7837             
7838             me.el = el;
7839             
7840             me.defaultUrl = null;
7841
7842             me.addEvents(
7843                 
7844                 BEFOREUPDATE,
7845                 
7846                 UPDATE,
7847                 
7848                 FAILURE
7849             );
7850
7851             Ext.apply(me, Ext.Updater.defaults);
7852             
7853             
7854             
7855             
7856             
7857             
7858
7859             
7860             me.transaction = null;
7861             
7862             me.refreshDelegate = me.refresh.createDelegate(me);
7863             
7864             me.updateDelegate = me.update.createDelegate(me);
7865             
7866             me.formUpdateDelegate = (me.formUpdate || function(){}).createDelegate(me);
7867
7868             
7869             me.renderer = me.renderer || me.getDefaultRenderer();
7870
7871             Ext.Updater.superclass.constructor.call(me);
7872         },
7873
7874         
7875         setRenderer : function(renderer){
7876             this.renderer = renderer;
7877         },
7878
7879         
7880         getRenderer : function(){
7881            return this.renderer;
7882         },
7883
7884         
7885         getDefaultRenderer: function() {
7886             return new Ext.Updater.BasicRenderer();
7887         },
7888
7889         
7890         setDefaultUrl : function(defaultUrl){
7891             this.defaultUrl = defaultUrl;
7892         },
7893
7894         
7895         getEl : function(){
7896             return this.el;
7897         },
7898
7899         
7900         update : function(url, params, callback, discardUrl){
7901             var me = this,
7902                 cfg,
7903                 callerScope;
7904
7905             if(me.fireEvent(BEFOREUPDATE, me.el, url, params) !== false){
7906                 if(Ext.isObject(url)){ 
7907                     cfg = url;
7908                     url = cfg.url;
7909                     params = params || cfg.params;
7910                     callback = callback || cfg.callback;
7911                     discardUrl = discardUrl || cfg.discardUrl;
7912                     callerScope = cfg.scope;
7913                     if(!Ext.isEmpty(cfg.nocache)){me.disableCaching = cfg.nocache;};
7914                     if(!Ext.isEmpty(cfg.text)){me.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
7915                     if(!Ext.isEmpty(cfg.scripts)){me.loadScripts = cfg.scripts;};
7916                     if(!Ext.isEmpty(cfg.timeout)){me.timeout = cfg.timeout;};
7917                 }
7918                 me.showLoading();
7919
7920                 if(!discardUrl){
7921                     me.defaultUrl = url;
7922                 }
7923                 if(Ext.isFunction(url)){
7924                     url = url.call(me);
7925                 }
7926
7927                 var o = Ext.apply({}, {
7928                     url : url,
7929                     params: (Ext.isFunction(params) && callerScope) ? params.createDelegate(callerScope) : params,
7930                     success: processSuccess,
7931                     failure: processFailure,
7932                     scope: me,
7933                     callback: undefined,
7934                     timeout: (me.timeout*1000),
7935                     disableCaching: me.disableCaching,
7936                     argument: {
7937                         "options": cfg,
7938                         "url": url,
7939                         "form": null,
7940                         "callback": callback,
7941                         "scope": callerScope || window,
7942                         "params": params
7943                     }
7944                 }, cfg);
7945
7946                 me.transaction = Ext.Ajax.request(o);
7947             }
7948         },
7949
7950         
7951         formUpdate : function(form, url, reset, callback){
7952             var me = this;
7953             if(me.fireEvent(BEFOREUPDATE, me.el, form, url) !== false){
7954                 if(Ext.isFunction(url)){
7955                     url = url.call(me);
7956                 }
7957                 form = Ext.getDom(form);
7958                 me.transaction = Ext.Ajax.request({
7959                     form: form,
7960                     url:url,
7961                     success: processSuccess,
7962                     failure: processFailure,
7963                     scope: me,
7964                     timeout: (me.timeout*1000),
7965                     argument: {
7966                         "url": url,
7967                         "form": form,
7968                         "callback": callback,
7969                         "reset": reset
7970                     }
7971                 });
7972                 me.showLoading.defer(1, me);
7973             }
7974         },
7975
7976         
7977         startAutoRefresh : function(interval, url, params, callback, refreshNow){
7978             var me = this;
7979             if(refreshNow){
7980                 me.update(url || me.defaultUrl, params, callback, true);
7981             }
7982             if(me.autoRefreshProcId){
7983                 clearInterval(me.autoRefreshProcId);
7984             }
7985             me.autoRefreshProcId = setInterval(me.update.createDelegate(me, [url || me.defaultUrl, params, callback, true]), interval * 1000);
7986         },
7987
7988         
7989         stopAutoRefresh : function(){
7990             if(this.autoRefreshProcId){
7991                 clearInterval(this.autoRefreshProcId);
7992                 delete this.autoRefreshProcId;
7993             }
7994         },
7995
7996         
7997         isAutoRefreshing : function(){
7998            return !!this.autoRefreshProcId;
7999         },
8000
8001         
8002         showLoading : function(){
8003             if(this.showLoadIndicator){
8004                 this.el.dom.innerHTML = this.indicatorText;
8005             }
8006         },
8007
8008         
8009         abort : function(){
8010             if(this.transaction){
8011                 Ext.Ajax.abort(this.transaction);
8012             }
8013         },
8014
8015         
8016         isUpdating : function(){
8017             return this.transaction ? Ext.Ajax.isLoading(this.transaction) : false;
8018         },
8019
8020         
8021         refresh : function(callback){
8022             if(this.defaultUrl){
8023                 this.update(this.defaultUrl, null, callback, true);
8024             }
8025         }
8026     };
8027 }());
8028
8029
8030 Ext.Updater.defaults = {
8031    
8032     timeout : 30,
8033     
8034     disableCaching : false,
8035     
8036     showLoadIndicator : true,
8037     
8038     indicatorText : '<div class="loading-indicator">Loading...</div>',
8039      
8040     loadScripts : false,
8041     
8042     sslBlankUrl : Ext.SSL_SECURE_URL
8043 };
8044
8045
8046
8047 Ext.Updater.updateElement = function(el, url, params, options){
8048     var um = Ext.get(el).getUpdater();
8049     Ext.apply(um, options);
8050     um.update(url, params, options ? options.callback : null);
8051 };
8052
8053
8054 Ext.Updater.BasicRenderer = function(){};
8055
8056 Ext.Updater.BasicRenderer.prototype = {
8057     
8058      render : function(el, response, updateManager, callback){
8059         el.update(response.responseText, updateManager.loadScripts, callback);
8060     }
8061 };
8062
8063
8064
8065 (function() {
8066
8067
8068 Date.useStrict = false;
8069
8070
8071
8072
8073
8074 function xf(format) {
8075     var args = Array.prototype.slice.call(arguments, 1);
8076     return format.replace(/\{(\d+)\}/g, function(m, i) {
8077         return args[i];
8078     });
8079 }
8080
8081
8082
8083 Date.formatCodeToRegex = function(character, currentGroup) {
8084     
8085     var p = Date.parseCodes[character];
8086
8087     if (p) {
8088       p = typeof p == 'function'? p() : p;
8089       Date.parseCodes[character] = p; 
8090     }
8091
8092     return p ? Ext.applyIf({
8093       c: p.c ? xf(p.c, currentGroup || "{0}") : p.c
8094     }, p) : {
8095         g:0,
8096         c:null,
8097         s:Ext.escapeRe(character) 
8098     };
8099 };
8100
8101
8102 var $f = Date.formatCodeToRegex;
8103
8104 Ext.apply(Date, {
8105     
8106     parseFunctions: {
8107         "M$": function(input, strict) {
8108             
8109             
8110             var re = new RegExp('\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/');
8111             var r = (input || '').match(re);
8112             return r? new Date(((r[1] || '') + r[2]) * 1) : null;
8113         }
8114     },
8115     parseRegexes: [],
8116
8117     
8118     formatFunctions: {
8119         "M$": function() {
8120             
8121             return '\\/Date(' + this.getTime() + ')\\/';
8122         }
8123     },
8124
8125     y2kYear : 50,
8126
8127     
8128     MILLI : "ms",
8129
8130     
8131     SECOND : "s",
8132
8133     
8134     MINUTE : "mi",
8135
8136     
8137     HOUR : "h",
8138
8139     
8140     DAY : "d",
8141
8142     
8143     MONTH : "mo",
8144
8145     
8146     YEAR : "y",
8147
8148     
8149     defaults: {},
8150
8151     
8152     dayNames : [
8153         "Sunday",
8154         "Monday",
8155         "Tuesday",
8156         "Wednesday",
8157         "Thursday",
8158         "Friday",
8159         "Saturday"
8160     ],
8161
8162     
8163     monthNames : [
8164         "January",
8165         "February",
8166         "March",
8167         "April",
8168         "May",
8169         "June",
8170         "July",
8171         "August",
8172         "September",
8173         "October",
8174         "November",
8175         "December"
8176     ],
8177
8178     
8179     monthNumbers : {
8180         Jan:0,
8181         Feb:1,
8182         Mar:2,
8183         Apr:3,
8184         May:4,
8185         Jun:5,
8186         Jul:6,
8187         Aug:7,
8188         Sep:8,
8189         Oct:9,
8190         Nov:10,
8191         Dec:11
8192     },
8193
8194     
8195     getShortMonthName : function(month) {
8196         return Date.monthNames[month].substring(0, 3);
8197     },
8198
8199     
8200     getShortDayName : function(day) {
8201         return Date.dayNames[day].substring(0, 3);
8202     },
8203
8204     
8205     getMonthNumber : function(name) {
8206         
8207         return Date.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
8208     },
8209
8210     
8211     formatCodes : {
8212         d: "String.leftPad(this.getDate(), 2, '0')",
8213         D: "Date.getShortDayName(this.getDay())", 
8214         j: "this.getDate()",
8215         l: "Date.dayNames[this.getDay()]",
8216         N: "(this.getDay() ? this.getDay() : 7)",
8217         S: "this.getSuffix()",
8218         w: "this.getDay()",
8219         z: "this.getDayOfYear()",
8220         W: "String.leftPad(this.getWeekOfYear(), 2, '0')",
8221         F: "Date.monthNames[this.getMonth()]",
8222         m: "String.leftPad(this.getMonth() + 1, 2, '0')",
8223         M: "Date.getShortMonthName(this.getMonth())", 
8224         n: "(this.getMonth() + 1)",
8225         t: "this.getDaysInMonth()",
8226         L: "(this.isLeapYear() ? 1 : 0)",
8227         o: "(this.getFullYear() + (this.getWeekOfYear() == 1 && this.getMonth() > 0 ? +1 : (this.getWeekOfYear() >= 52 && this.getMonth() < 11 ? -1 : 0)))",
8228         Y: "String.leftPad(this.getFullYear(), 4, '0')",
8229         y: "('' + this.getFullYear()).substring(2, 4)",
8230         a: "(this.getHours() < 12 ? 'am' : 'pm')",
8231         A: "(this.getHours() < 12 ? 'AM' : 'PM')",
8232         g: "((this.getHours() % 12) ? this.getHours() % 12 : 12)",
8233         G: "this.getHours()",
8234         h: "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')",
8235         H: "String.leftPad(this.getHours(), 2, '0')",
8236         i: "String.leftPad(this.getMinutes(), 2, '0')",
8237         s: "String.leftPad(this.getSeconds(), 2, '0')",
8238         u: "String.leftPad(this.getMilliseconds(), 3, '0')",
8239         O: "this.getGMTOffset()",
8240         P: "this.getGMTOffset(true)",
8241         T: "this.getTimezone()",
8242         Z: "(this.getTimezoneOffset() * -60)",
8243
8244         c: function() { 
8245             for (var c = "Y-m-dTH:i:sP", code = [], i = 0, l = c.length; i < l; ++i) {
8246                 var e = c.charAt(i);
8247                 code.push(e == "T" ? "'T'" : Date.getFormatCode(e)); 
8248             }
8249             return code.join(" + ");
8250         },
8251         
8252
8253         U: "Math.round(this.getTime() / 1000)"
8254     },
8255
8256     
8257     isValid : function(y, m, d, h, i, s, ms) {
8258         
8259         h = h || 0;
8260         i = i || 0;
8261         s = s || 0;
8262         ms = ms || 0;
8263
8264         
8265         var dt = new Date(y < 100 ? 100 : y, m - 1, d, h, i, s, ms).add(Date.YEAR, y < 100 ? y - 100 : 0);
8266
8267         return y == dt.getFullYear() &&
8268             m == dt.getMonth() + 1 &&
8269             d == dt.getDate() &&
8270             h == dt.getHours() &&
8271             i == dt.getMinutes() &&
8272             s == dt.getSeconds() &&
8273             ms == dt.getMilliseconds();
8274     },
8275
8276     
8277     parseDate : function(input, format, strict) {
8278         var p = Date.parseFunctions;
8279         if (p[format] == null) {
8280             Date.createParser(format);
8281         }
8282         return p[format](input, Ext.isDefined(strict) ? strict : Date.useStrict);
8283     },
8284
8285     
8286     getFormatCode : function(character) {
8287         var f = Date.formatCodes[character];
8288
8289         if (f) {
8290           f = typeof f == 'function'? f() : f;
8291           Date.formatCodes[character] = f; 
8292         }
8293
8294         
8295         return f || ("'" + String.escape(character) + "'");
8296     },
8297
8298     
8299     createFormat : function(format) {
8300         var code = [],
8301             special = false,
8302             ch = '';
8303
8304         for (var i = 0; i < format.length; ++i) {
8305             ch = format.charAt(i);
8306             if (!special && ch == "\\") {
8307                 special = true;
8308             } else if (special) {
8309                 special = false;
8310                 code.push("'" + String.escape(ch) + "'");
8311             } else {
8312                 code.push(Date.getFormatCode(ch));
8313             }
8314         }
8315         Date.formatFunctions[format] = new Function("return " + code.join('+'));
8316     },
8317
8318     
8319     createParser : function() {
8320         var code = [
8321             "var dt, y, m, d, h, i, s, ms, o, z, zz, u, v,",
8322                 "def = Date.defaults,",
8323                 "results = String(input).match(Date.parseRegexes[{0}]);", 
8324
8325             "if(results){",
8326                 "{1}",
8327
8328                 "if(u != null){", 
8329                     "v = new Date(u * 1000);", 
8330                 "}else{",
8331                     
8332                     
8333                     
8334                     "dt = (new Date()).clearTime();",
8335
8336                     
8337                     "y = Ext.num(y, Ext.num(def.y, dt.getFullYear()));",
8338                     "m = Ext.num(m, Ext.num(def.m - 1, dt.getMonth()));",
8339                     "d = Ext.num(d, Ext.num(def.d, dt.getDate()));",
8340
8341                     
8342                     "h  = Ext.num(h, Ext.num(def.h, dt.getHours()));",
8343                     "i  = Ext.num(i, Ext.num(def.i, dt.getMinutes()));",
8344                     "s  = Ext.num(s, Ext.num(def.s, dt.getSeconds()));",
8345                     "ms = Ext.num(ms, Ext.num(def.ms, dt.getMilliseconds()));",
8346
8347                     "if(z >= 0 && y >= 0){",
8348                         
8349                         
8350
8351                         
8352                         
8353                         "v = new Date(y < 100 ? 100 : y, 0, 1, h, i, s, ms).add(Date.YEAR, y < 100 ? y - 100 : 0);",
8354
8355                         
8356                         "v = !strict? v : (strict === true && (z <= 364 || (v.isLeapYear() && z <= 365))? v.add(Date.DAY, z) : null);",
8357                     "}else if(strict === true && !Date.isValid(y, m + 1, d, h, i, s, ms)){", 
8358                         "v = null;", 
8359                     "}else{",
8360                         
8361                         
8362                         "v = new Date(y < 100 ? 100 : y, m, d, h, i, s, ms).add(Date.YEAR, y < 100 ? y - 100 : 0);",
8363                     "}",
8364                 "}",
8365             "}",
8366
8367             "if(v){",
8368                 
8369                 "if(zz != null){",
8370                     
8371                     "v = v.add(Date.SECOND, -v.getTimezoneOffset() * 60 - zz);",
8372                 "}else if(o){",
8373                     
8374                     "v = v.add(Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));",
8375                 "}",
8376             "}",
8377
8378             "return v;"
8379         ].join('\n');
8380
8381         return function(format) {
8382             var regexNum = Date.parseRegexes.length,
8383                 currentGroup = 1,
8384                 calc = [],
8385                 regex = [],
8386                 special = false,
8387                 ch = "",
8388                 i = 0,
8389                 obj,
8390                 last;
8391
8392             for (; i < format.length; ++i) {
8393                 ch = format.charAt(i);
8394                 if (!special && ch == "\\") {
8395                     special = true;
8396                 } else if (special) {
8397                     special = false;
8398                     regex.push(String.escape(ch));
8399                 } else {
8400                     obj = $f(ch, currentGroup);
8401                     currentGroup += obj.g;
8402                     regex.push(obj.s);
8403                     if (obj.g && obj.c) {
8404                         if (obj.calcLast) {
8405                             last = obj.c;
8406                         } else {
8407                             calc.push(obj.c);
8408                         }
8409                     }
8410                 }
8411             }
8412             
8413             if (last) {
8414                 calc.push(last);
8415             }
8416
8417             Date.parseRegexes[regexNum] = new RegExp("^" + regex.join('') + "$", 'i');
8418             Date.parseFunctions[format] = new Function("input", "strict", xf(code, regexNum, calc.join('')));
8419         };
8420     }(),
8421
8422     
8423     parseCodes : {
8424         
8425         d: {
8426             g:1,
8427             c:"d = parseInt(results[{0}], 10);\n",
8428             s:"(\\d{2})" 
8429         },
8430         j: {
8431             g:1,
8432             c:"d = parseInt(results[{0}], 10);\n",
8433             s:"(\\d{1,2})" 
8434         },
8435         D: function() {
8436             for (var a = [], i = 0; i < 7; a.push(Date.getShortDayName(i)), ++i); 
8437             return {
8438                 g:0,
8439                 c:null,
8440                 s:"(?:" + a.join("|") +")"
8441             };
8442         },
8443         l: function() {
8444             return {
8445                 g:0,
8446                 c:null,
8447                 s:"(?:" + Date.dayNames.join("|") + ")"
8448             };
8449         },
8450         N: {
8451             g:0,
8452             c:null,
8453             s:"[1-7]" 
8454         },
8455         S: {
8456             g:0,
8457             c:null,
8458             s:"(?:st|nd|rd|th)"
8459         },
8460         w: {
8461             g:0,
8462             c:null,
8463             s:"[0-6]" 
8464         },
8465         z: {
8466             g:1,
8467             c:"z = parseInt(results[{0}], 10);\n",
8468             s:"(\\d{1,3})" 
8469         },
8470         W: {
8471             g:0,
8472             c:null,
8473             s:"(?:\\d{2})" 
8474         },
8475         F: function() {
8476             return {
8477                 g:1,
8478                 c:"m = parseInt(Date.getMonthNumber(results[{0}]), 10);\n", 
8479                 s:"(" + Date.monthNames.join("|") + ")"
8480             };
8481         },
8482         M: function() {
8483             for (var a = [], i = 0; i < 12; a.push(Date.getShortMonthName(i)), ++i); 
8484             return Ext.applyIf({
8485                 s:"(" + a.join("|") + ")"
8486             }, $f("F"));
8487         },
8488         m: {
8489             g:1,
8490             c:"m = parseInt(results[{0}], 10) - 1;\n",
8491             s:"(\\d{2})" 
8492         },
8493         n: {
8494             g:1,
8495             c:"m = parseInt(results[{0}], 10) - 1;\n",
8496             s:"(\\d{1,2})" 
8497         },
8498         t: {
8499             g:0,
8500             c:null,
8501             s:"(?:\\d{2})" 
8502         },
8503         L: {
8504             g:0,
8505             c:null,
8506             s:"(?:1|0)"
8507         },
8508         o: function() {
8509             return $f("Y");
8510         },
8511         Y: {
8512             g:1,
8513             c:"y = parseInt(results[{0}], 10);\n",
8514             s:"(\\d{4})" 
8515         },
8516         y: {
8517             g:1,
8518             c:"var ty = parseInt(results[{0}], 10);\n"
8519                 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n", 
8520             s:"(\\d{1,2})"
8521         },
8522         
8523         a: function(){
8524             return $f("A");
8525         },
8526         A: {
8527             
8528             calcLast: true,
8529             g:1,
8530             c:"if (/(am)/i.test(results[{0}])) {\n"
8531                 + "if (!h || h == 12) { h = 0; }\n"
8532                 + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
8533             s:"(AM|PM|am|pm)"
8534         },
8535         g: function() {
8536             return $f("G");
8537         },
8538         G: {
8539             g:1,
8540             c:"h = parseInt(results[{0}], 10);\n",
8541             s:"(\\d{1,2})" 
8542         },
8543         h: function() {
8544             return $f("H");
8545         },
8546         H: {
8547             g:1,
8548             c:"h = parseInt(results[{0}], 10);\n",
8549             s:"(\\d{2})" 
8550         },
8551         i: {
8552             g:1,
8553             c:"i = parseInt(results[{0}], 10);\n",
8554             s:"(\\d{2})" 
8555         },
8556         s: {
8557             g:1,
8558             c:"s = parseInt(results[{0}], 10);\n",
8559             s:"(\\d{2})" 
8560         },
8561         u: {
8562             g:1,
8563             c:"ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",
8564             s:"(\\d+)" 
8565         },
8566         O: {
8567             g:1,
8568             c:[
8569                 "o = results[{0}];",
8570                 "var sn = o.substring(0,1),", 
8571                     "hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),", 
8572                     "mn = o.substring(3,5) % 60;", 
8573                 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n" 
8574             ].join("\n"),
8575             s: "([+\-]\\d{4})" 
8576         },
8577         P: {
8578             g:1,
8579             c:[
8580                 "o = results[{0}];",
8581                 "var sn = o.substring(0,1),", 
8582                     "hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),", 
8583                     "mn = o.substring(4,6) % 60;", 
8584                 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n" 
8585             ].join("\n"),
8586             s: "([+\-]\\d{2}:\\d{2})" 
8587         },
8588         T: {
8589             g:0,
8590             c:null,
8591             s:"[A-Z]{1,4}" 
8592         },
8593         Z: {
8594             g:1,
8595             c:"zz = results[{0}] * 1;\n" 
8596                   + "zz = (-43200 <= zz && zz <= 50400)? zz : null;\n",
8597             s:"([+\-]?\\d{1,5})" 
8598         },
8599         c: function() {
8600             var calc = [],
8601                 arr = [
8602                     $f("Y", 1), 
8603                     $f("m", 2), 
8604                     $f("d", 3), 
8605                     $f("h", 4), 
8606                     $f("i", 5), 
8607                     $f("s", 6), 
8608                     {c:"ms = results[7] || '0'; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"}, 
8609                     {c:[ 
8610                         "if(results[8]) {", 
8611                             "if(results[8] == 'Z'){",
8612                                 "zz = 0;", 
8613                             "}else if (results[8].indexOf(':') > -1){",
8614                                 $f("P", 8).c, 
8615                             "}else{",
8616                                 $f("O", 8).c, 
8617                             "}",
8618                         "}"
8619                     ].join('\n')}
8620                 ];
8621
8622             for (var i = 0, l = arr.length; i < l; ++i) {
8623                 calc.push(arr[i].c);
8624             }
8625
8626             return {
8627                 g:1,
8628                 c:calc.join(""),
8629                 s:[
8630                     arr[0].s, 
8631                     "(?:", "-", arr[1].s, 
8632                         "(?:", "-", arr[2].s, 
8633                             "(?:",
8634                                 "(?:T| )?", 
8635                                 arr[3].s, ":", arr[4].s,  
8636                                 "(?::", arr[5].s, ")?", 
8637                                 "(?:(?:\\.|,)(\\d+))?", 
8638                                 "(Z|(?:[-+]\\d{2}(?::)?\\d{2}))?", 
8639                             ")?",
8640                         ")?",
8641                     ")?"
8642                 ].join("")
8643             };
8644         },
8645         U: {
8646             g:1,
8647             c:"u = parseInt(results[{0}], 10);\n",
8648             s:"(-?\\d+)" 
8649         }
8650     }
8651 });
8652
8653 }());
8654
8655 Ext.apply(Date.prototype, {
8656     
8657     dateFormat : function(format) {
8658         if (Date.formatFunctions[format] == null) {
8659             Date.createFormat(format);
8660         }
8661         return Date.formatFunctions[format].call(this);
8662     },
8663
8664     
8665     getTimezone : function() {
8666         
8667         
8668         
8669         
8670         
8671         
8672         
8673         
8674         
8675         
8676         
8677         
8678         return this.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, "");
8679     },
8680
8681     
8682     getGMTOffset : function(colon) {
8683         return (this.getTimezoneOffset() > 0 ? "-" : "+")
8684             + String.leftPad(Math.floor(Math.abs(this.getTimezoneOffset()) / 60), 2, "0")
8685             + (colon ? ":" : "")
8686             + String.leftPad(Math.abs(this.getTimezoneOffset() % 60), 2, "0");
8687     },
8688
8689     
8690     getDayOfYear: function() {
8691         var num = 0,
8692             d = this.clone(),
8693             m = this.getMonth(),
8694             i;
8695
8696         for (i = 0, d.setDate(1), d.setMonth(0); i < m; d.setMonth(++i)) {
8697             num += d.getDaysInMonth();
8698         }
8699         return num + this.getDate() - 1;
8700     },
8701
8702     
8703     getWeekOfYear : function() {
8704         
8705         var ms1d = 864e5, 
8706             ms7d = 7 * ms1d; 
8707
8708         return function() { 
8709             var DC3 = Date.UTC(this.getFullYear(), this.getMonth(), this.getDate() + 3) / ms1d, 
8710                 AWN = Math.floor(DC3 / 7), 
8711                 Wyr = new Date(AWN * ms7d).getUTCFullYear();
8712
8713             return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
8714         };
8715     }(),
8716
8717     
8718     isLeapYear : function() {
8719         var year = this.getFullYear();
8720         return !!((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
8721     },
8722
8723     
8724     getFirstDayOfMonth : function() {
8725         var day = (this.getDay() - (this.getDate() - 1)) % 7;
8726         return (day < 0) ? (day + 7) : day;
8727     },
8728
8729     
8730     getLastDayOfMonth : function() {
8731         return this.getLastDateOfMonth().getDay();
8732     },
8733
8734
8735     
8736     getFirstDateOfMonth : function() {
8737         return new Date(this.getFullYear(), this.getMonth(), 1);
8738     },
8739
8740     
8741     getLastDateOfMonth : function() {
8742         return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
8743     },
8744
8745     
8746     getDaysInMonth: function() {
8747         var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
8748
8749         return function() { 
8750             var m = this.getMonth();
8751
8752             return m == 1 && this.isLeapYear() ? 29 : daysInMonth[m];
8753         };
8754     }(),
8755
8756     
8757     getSuffix : function() {
8758         switch (this.getDate()) {
8759             case 1:
8760             case 21:
8761             case 31:
8762                 return "st";
8763             case 2:
8764             case 22:
8765                 return "nd";
8766             case 3:
8767             case 23:
8768                 return "rd";
8769             default:
8770                 return "th";
8771         }
8772     },
8773
8774     
8775     clone : function() {
8776         return new Date(this.getTime());
8777     },
8778
8779     
8780     isDST : function() {
8781         
8782         
8783         return new Date(this.getFullYear(), 0, 1).getTimezoneOffset() != this.getTimezoneOffset();
8784     },
8785
8786     
8787     clearTime : function(clone) {
8788         if (clone) {
8789             return this.clone().clearTime();
8790         }
8791
8792         
8793         var d = this.getDate();
8794
8795         
8796         this.setHours(0);
8797         this.setMinutes(0);
8798         this.setSeconds(0);
8799         this.setMilliseconds(0);
8800
8801         if (this.getDate() != d) { 
8802             
8803             
8804
8805             
8806             for (var hr = 1, c = this.add(Date.HOUR, hr); c.getDate() != d; hr++, c = this.add(Date.HOUR, hr));
8807
8808             this.setDate(d);
8809             this.setHours(c.getHours());
8810         }
8811
8812         return this;
8813     },
8814
8815     
8816     add : function(interval, value) {
8817         var d = this.clone();
8818         if (!interval || value === 0) return d;
8819
8820         switch(interval.toLowerCase()) {
8821             case Date.MILLI:
8822                 d.setMilliseconds(this.getMilliseconds() + value);
8823                 break;
8824             case Date.SECOND:
8825                 d.setSeconds(this.getSeconds() + value);
8826                 break;
8827             case Date.MINUTE:
8828                 d.setMinutes(this.getMinutes() + value);
8829                 break;
8830             case Date.HOUR:
8831                 d.setHours(this.getHours() + value);
8832                 break;
8833             case Date.DAY:
8834                 d.setDate(this.getDate() + value);
8835                 break;
8836             case Date.MONTH:
8837                 var day = this.getDate();
8838                 if (day > 28) {
8839                     day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
8840                 }
8841                 d.setDate(day);
8842                 d.setMonth(this.getMonth() + value);
8843                 break;
8844             case Date.YEAR:
8845                 d.setFullYear(this.getFullYear() + value);
8846                 break;
8847         }
8848         return d;
8849     },
8850
8851     
8852     between : function(start, end) {
8853         var t = this.getTime();
8854         return start.getTime() <= t && t <= end.getTime();
8855     }
8856 });
8857
8858
8859
8860 Date.prototype.format = Date.prototype.dateFormat;
8861
8862
8863
8864 if (Ext.isSafari && (navigator.userAgent.match(/WebKit\/(\d+)/)[1] || NaN) < 420) {
8865     Ext.apply(Date.prototype, {
8866         _xMonth : Date.prototype.setMonth,
8867         _xDate  : Date.prototype.setDate,
8868
8869         
8870         
8871         setMonth : function(num) {
8872             if (num <= -1) {
8873                 var n = Math.ceil(-num),
8874                     back_year = Math.ceil(n / 12),
8875                     month = (n % 12) ? 12 - n % 12 : 0;
8876
8877                 this.setFullYear(this.getFullYear() - back_year);
8878
8879                 return this._xMonth(month);
8880             } else {
8881                 return this._xMonth(num);
8882             }
8883         },
8884
8885         
8886         
8887         
8888         setDate : function(d) {
8889             
8890             
8891             return this.setTime(this.getTime() - (this.getDate() - d) * 864e5);
8892         }
8893     });
8894 }
8895
8896
8897
8898
8899
8900 Ext.util.MixedCollection = function(allowFunctions, keyFn){
8901     this.items = [];
8902     this.map = {};
8903     this.keys = [];
8904     this.length = 0;
8905     this.addEvents(
8906         
8907         'clear',
8908         
8909         'add',
8910         
8911         'replace',
8912         
8913         'remove',
8914         'sort'
8915     );
8916     this.allowFunctions = allowFunctions === true;
8917     if(keyFn){
8918         this.getKey = keyFn;
8919     }
8920     Ext.util.MixedCollection.superclass.constructor.call(this);
8921 };
8922
8923 Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {
8924
8925     
8926     allowFunctions : false,
8927
8928     
8929     add : function(key, o){
8930         if(arguments.length == 1){
8931             o = arguments[0];
8932             key = this.getKey(o);
8933         }
8934         if(typeof key != 'undefined' && key !== null){
8935             var old = this.map[key];
8936             if(typeof old != 'undefined'){
8937                 return this.replace(key, o);
8938             }
8939             this.map[key] = o;
8940         }
8941         this.length++;
8942         this.items.push(o);
8943         this.keys.push(key);
8944         this.fireEvent('add', this.length-1, o, key);
8945         return o;
8946     },
8947
8948     
8949     getKey : function(o){
8950          return o.id;
8951     },
8952
8953     
8954     replace : function(key, o){
8955         if(arguments.length == 1){
8956             o = arguments[0];
8957             key = this.getKey(o);
8958         }
8959         var old = this.map[key];
8960         if(typeof key == 'undefined' || key === null || typeof old == 'undefined'){
8961              return this.add(key, o);
8962         }
8963         var index = this.indexOfKey(key);
8964         this.items[index] = o;
8965         this.map[key] = o;
8966         this.fireEvent('replace', key, old, o);
8967         return o;
8968     },
8969
8970     
8971     addAll : function(objs){
8972         if(arguments.length > 1 || Ext.isArray(objs)){
8973             var args = arguments.length > 1 ? arguments : objs;
8974             for(var i = 0, len = args.length; i < len; i++){
8975                 this.add(args[i]);
8976             }
8977         }else{
8978             for(var key in objs){
8979                 if(this.allowFunctions || typeof objs[key] != 'function'){
8980                     this.add(key, objs[key]);
8981                 }
8982             }
8983         }
8984     },
8985
8986     
8987     each : function(fn, scope){
8988         var items = [].concat(this.items); 
8989         for(var i = 0, len = items.length; i < len; i++){
8990             if(fn.call(scope || items[i], items[i], i, len) === false){
8991                 break;
8992             }
8993         }
8994     },
8995
8996     
8997     eachKey : function(fn, scope){
8998         for(var i = 0, len = this.keys.length; i < len; i++){
8999             fn.call(scope || window, this.keys[i], this.items[i], i, len);
9000         }
9001     },
9002
9003     
9004     find : function(fn, scope){
9005         for(var i = 0, len = this.items.length; i < len; i++){
9006             if(fn.call(scope || window, this.items[i], this.keys[i])){
9007                 return this.items[i];
9008             }
9009         }
9010         return null;
9011     },
9012
9013     
9014     insert : function(index, key, o){
9015         if(arguments.length == 2){
9016             o = arguments[1];
9017             key = this.getKey(o);
9018         }
9019         if(this.containsKey(key)){
9020             this.suspendEvents();
9021             this.removeKey(key);
9022             this.resumeEvents();
9023         }
9024         if(index >= this.length){
9025             return this.add(key, o);
9026         }
9027         this.length++;
9028         this.items.splice(index, 0, o);
9029         if(typeof key != 'undefined' && key !== null){
9030             this.map[key] = o;
9031         }
9032         this.keys.splice(index, 0, key);
9033         this.fireEvent('add', index, o, key);
9034         return o;
9035     },
9036
9037     
9038     remove : function(o){
9039         return this.removeAt(this.indexOf(o));
9040     },
9041
9042     
9043     removeAt : function(index){
9044         if(index < this.length && index >= 0){
9045             this.length--;
9046             var o = this.items[index];
9047             this.items.splice(index, 1);
9048             var key = this.keys[index];
9049             if(typeof key != 'undefined'){
9050                 delete this.map[key];
9051             }
9052             this.keys.splice(index, 1);
9053             this.fireEvent('remove', o, key);
9054             return o;
9055         }
9056         return false;
9057     },
9058
9059     
9060     removeKey : function(key){
9061         return this.removeAt(this.indexOfKey(key));
9062     },
9063
9064     
9065     getCount : function(){
9066         return this.length;
9067     },
9068
9069     
9070     indexOf : function(o){
9071         return this.items.indexOf(o);
9072     },
9073
9074     
9075     indexOfKey : function(key){
9076         return this.keys.indexOf(key);
9077     },
9078
9079     
9080     item : function(key){
9081         var mk = this.map[key],
9082             item = mk !== undefined ? mk : (typeof key == 'number') ? this.items[key] : undefined;
9083         return typeof item != 'function' || this.allowFunctions ? item : null; 
9084     },
9085
9086     
9087     itemAt : function(index){
9088         return this.items[index];
9089     },
9090
9091     
9092     key : function(key){
9093         return this.map[key];
9094     },
9095
9096     
9097     contains : function(o){
9098         return this.indexOf(o) != -1;
9099     },
9100
9101     
9102     containsKey : function(key){
9103         return typeof this.map[key] != 'undefined';
9104     },
9105
9106     
9107     clear : function(){
9108         this.length = 0;
9109         this.items = [];
9110         this.keys = [];
9111         this.map = {};
9112         this.fireEvent('clear');
9113     },
9114
9115     
9116     first : function(){
9117         return this.items[0];
9118     },
9119
9120     
9121     last : function(){
9122         return this.items[this.length-1];
9123     },
9124
9125     
9126     _sort : function(property, dir, fn){
9127         var i, len,
9128             dsc   = String(dir).toUpperCase() == 'DESC' ? -1 : 1,
9129
9130             
9131             c     = [],
9132             keys  = this.keys,
9133             items = this.items;
9134
9135         
9136         fn = fn || function(a, b) {
9137             return a - b;
9138         };
9139
9140         
9141         for(i = 0, len = items.length; i < len; i++){
9142             c[c.length] = {
9143                 key  : keys[i],
9144                 value: items[i],
9145                 index: i
9146             };
9147         }
9148
9149         
9150         c.sort(function(a, b){
9151             var v = fn(a[property], b[property]) * dsc;
9152             if(v === 0){
9153                 v = (a.index < b.index ? -1 : 1);
9154             }
9155             return v;
9156         });
9157
9158         
9159         for(i = 0, len = c.length; i < len; i++){
9160             items[i] = c[i].value;
9161             keys[i]  = c[i].key;
9162         }
9163
9164         this.fireEvent('sort', this);
9165     },
9166
9167     
9168     sort : function(dir, fn){
9169         this._sort('value', dir, fn);
9170     },
9171
9172     
9173     reorder: function(mapping) {
9174         this.suspendEvents();
9175
9176         var items = this.items,
9177             index = 0,
9178             length = items.length,
9179             order = [],
9180             remaining = [],
9181             oldIndex;
9182
9183         
9184         for (oldIndex in mapping) {
9185             order[mapping[oldIndex]] = items[oldIndex];
9186         }
9187
9188         for (index = 0; index < length; index++) {
9189             if (mapping[index] == undefined) {
9190                 remaining.push(items[index]);
9191             }
9192         }
9193
9194         for (index = 0; index < length; index++) {
9195             if (order[index] == undefined) {
9196                 order[index] = remaining.shift();
9197             }
9198         }
9199
9200         this.clear();
9201         this.addAll(order);
9202
9203         this.resumeEvents();
9204         this.fireEvent('sort', this);
9205     },
9206
9207     
9208     keySort : function(dir, fn){
9209         this._sort('key', dir, fn || function(a, b){
9210             var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();
9211             return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
9212         });
9213     },
9214
9215     
9216     getRange : function(start, end){
9217         var items = this.items;
9218         if(items.length < 1){
9219             return [];
9220         }
9221         start = start || 0;
9222         end = Math.min(typeof end == 'undefined' ? this.length-1 : end, this.length-1);
9223         var i, r = [];
9224         if(start <= end){
9225             for(i = start; i <= end; i++) {
9226                 r[r.length] = items[i];
9227             }
9228         }else{
9229             for(i = start; i >= end; i--) {
9230                 r[r.length] = items[i];
9231             }
9232         }
9233         return r;
9234     },
9235
9236     
9237     filter : function(property, value, anyMatch, caseSensitive){
9238         if(Ext.isEmpty(value, false)){
9239             return this.clone();
9240         }
9241         value = this.createValueMatcher(value, anyMatch, caseSensitive);
9242         return this.filterBy(function(o){
9243             return o && value.test(o[property]);
9244         });
9245     },
9246
9247     
9248     filterBy : function(fn, scope){
9249         var r = new Ext.util.MixedCollection();
9250         r.getKey = this.getKey;
9251         var k = this.keys, it = this.items;
9252         for(var i = 0, len = it.length; i < len; i++){
9253             if(fn.call(scope||this, it[i], k[i])){
9254                 r.add(k[i], it[i]);
9255             }
9256         }
9257         return r;
9258     },
9259
9260     
9261     findIndex : function(property, value, start, anyMatch, caseSensitive){
9262         if(Ext.isEmpty(value, false)){
9263             return -1;
9264         }
9265         value = this.createValueMatcher(value, anyMatch, caseSensitive);
9266         return this.findIndexBy(function(o){
9267             return o && value.test(o[property]);
9268         }, null, start);
9269     },
9270
9271     
9272     findIndexBy : function(fn, scope, start){
9273         var k = this.keys, it = this.items;
9274         for(var i = (start||0), len = it.length; i < len; i++){
9275             if(fn.call(scope||this, it[i], k[i])){
9276                 return i;
9277             }
9278         }
9279         return -1;
9280     },
9281
9282     
9283     createValueMatcher : function(value, anyMatch, caseSensitive, exactMatch) {
9284         if (!value.exec) { 
9285             var er = Ext.escapeRe;
9286             value = String(value);
9287
9288             if (anyMatch === true) {
9289                 value = er(value);
9290             } else {
9291                 value = '^' + er(value);
9292                 if (exactMatch === true) {
9293                     value += '$';
9294                 }
9295             }
9296             value = new RegExp(value, caseSensitive ? '' : 'i');
9297          }
9298          return value;
9299     },
9300
9301     
9302     clone : function(){
9303         var r = new Ext.util.MixedCollection();
9304         var k = this.keys, it = this.items;
9305         for(var i = 0, len = it.length; i < len; i++){
9306             r.add(k[i], it[i]);
9307         }
9308         r.getKey = this.getKey;
9309         return r;
9310     }
9311 });
9312
9313 Ext.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;
9314
9315 Ext.AbstractManager = Ext.extend(Object, {
9316     typeName: 'type',
9317     
9318     constructor: function(config) {
9319         Ext.apply(this, config || {});
9320         
9321         
9322         this.all = new Ext.util.MixedCollection();
9323         
9324         this.types = {};
9325     },
9326     
9327     
9328     get : function(id){
9329         return this.all.get(id);
9330     },
9331     
9332     
9333     register: function(item) {
9334         this.all.add(item);
9335     },
9336     
9337     
9338     unregister: function(item) {
9339         this.all.remove(item);        
9340     },
9341     
9342     
9343     registerType : function(type, cls){
9344         this.types[type] = cls;
9345         cls[this.typeName] = type;
9346     },
9347     
9348     
9349     isRegistered : function(type){
9350         return this.types[type] !== undefined;    
9351     },
9352     
9353     
9354     create: function(config, defaultType) {
9355         var type        = config[this.typeName] || config.type || defaultType,
9356             Constructor = this.types[type];
9357         
9358         if (Constructor == undefined) {
9359             throw new Error(String.format("The '{0}' type has not been registered with this manager", type));
9360         }
9361         
9362         return new Constructor(config);
9363     },
9364     
9365     
9366     onAvailable : function(id, fn, scope){
9367         var all = this.all;
9368         
9369         all.on("add", function(index, o){
9370             if (o.id == id) {
9371                 fn.call(scope || o, o);
9372                 all.un("add", fn, scope);
9373             }
9374         });
9375     }
9376 });
9377 Ext.util.Format = function() {
9378     var trimRe         = /^\s+|\s+$/g,
9379         stripTagsRE    = /<\/?[^>]+>/gi,
9380         stripScriptsRe = /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,
9381         nl2brRe        = /\r?\n/g;
9382
9383     return {
9384         
9385         ellipsis : function(value, len, word) {
9386             if (value && value.length > len) {
9387                 if (word) {
9388                     var vs    = value.substr(0, len - 2),
9389                         index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));
9390                     if (index == -1 || index < (len - 15)) {
9391                         return value.substr(0, len - 3) + "...";
9392                     } else {
9393                         return vs.substr(0, index) + "...";
9394                     }
9395                 } else {
9396                     return value.substr(0, len - 3) + "...";
9397                 }
9398             }
9399             return value;
9400         },
9401
9402         
9403         undef : function(value) {
9404             return value !== undefined ? value : "";
9405         },
9406
9407         
9408         defaultValue : function(value, defaultValue) {
9409             return value !== undefined && value !== '' ? value : defaultValue;
9410         },
9411
9412         
9413         htmlEncode : function(value) {
9414             return !value ? value : String(value).replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
9415         },
9416
9417         
9418         htmlDecode : function(value) {
9419             return !value ? value : String(value).replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&quot;/g, '"').replace(/&amp;/g, "&");
9420         },
9421
9422         
9423         trim : function(value) {
9424             return String(value).replace(trimRe, "");
9425         },
9426
9427         
9428         substr : function(value, start, length) {
9429             return String(value).substr(start, length);
9430         },
9431
9432         
9433         lowercase : function(value) {
9434             return String(value).toLowerCase();
9435         },
9436
9437         
9438         uppercase : function(value) {
9439             return String(value).toUpperCase();
9440         },
9441
9442         
9443         capitalize : function(value) {
9444             return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
9445         },
9446
9447         
9448         call : function(value, fn) {
9449             if (arguments.length > 2) {
9450                 var args = Array.prototype.slice.call(arguments, 2);
9451                 args.unshift(value);
9452                 return eval(fn).apply(window, args);
9453             } else {
9454                 return eval(fn).call(window, value);
9455             }
9456         },
9457
9458         
9459         usMoney : function(v) {
9460             v = (Math.round((v-0)*100))/100;
9461             v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
9462             v = String(v);
9463             var ps = v.split('.'),
9464                 whole = ps[0],
9465                 sub = ps[1] ? '.'+ ps[1] : '.00',
9466                 r = /(\d+)(\d{3})/;
9467             while (r.test(whole)) {
9468                 whole = whole.replace(r, '$1' + ',' + '$2');
9469             }
9470             v = whole + sub;
9471             if (v.charAt(0) == '-') {
9472                 return '-$' + v.substr(1);
9473             }
9474             return "$" +  v;
9475         },
9476
9477         
9478         date : function(v, format) {
9479             if (!v) {
9480                 return "";
9481             }
9482             if (!Ext.isDate(v)) {
9483                 v = new Date(Date.parse(v));
9484             }
9485             return v.dateFormat(format || "m/d/Y");
9486         },
9487
9488         
9489         dateRenderer : function(format) {
9490             return function(v) {
9491                 return Ext.util.Format.date(v, format);
9492             };
9493         },
9494
9495         
9496         stripTags : function(v) {
9497             return !v ? v : String(v).replace(stripTagsRE, "");
9498         },
9499
9500         
9501         stripScripts : function(v) {
9502             return !v ? v : String(v).replace(stripScriptsRe, "");
9503         },
9504
9505         
9506         fileSize : function(size) {
9507             if (size < 1024) {
9508                 return size + " bytes";
9509             } else if (size < 1048576) {
9510                 return (Math.round(((size*10) / 1024))/10) + " KB";
9511             } else {
9512                 return (Math.round(((size*10) / 1048576))/10) + " MB";
9513             }
9514         },
9515
9516         
9517         math : function(){
9518             var fns = {};
9519             
9520             return function(v, a){
9521                 if (!fns[a]) {
9522                     fns[a] = new Function('v', 'return v ' + a + ';');
9523                 }
9524                 return fns[a](v);
9525             };
9526         }(),
9527
9528         
9529         round : function(value, precision) {
9530             var result = Number(value);
9531             if (typeof precision == 'number') {
9532                 precision = Math.pow(10, precision);
9533                 result = Math.round(value * precision) / precision;
9534             }
9535             return result;
9536         },
9537
9538         
9539         number: function(v, format) {
9540             if (!format) {
9541                 return v;
9542             }
9543             v = Ext.num(v, NaN);
9544             if (isNaN(v)) {
9545                 return '';
9546             }
9547             var comma = ',',
9548                 dec   = '.',
9549                 i18n  = false,
9550                 neg   = v < 0;
9551
9552             v = Math.abs(v);
9553             if (format.substr(format.length - 2) == '/i') {
9554                 format = format.substr(0, format.length - 2);
9555                 i18n   = true;
9556                 comma  = '.';
9557                 dec    = ',';
9558             }
9559
9560             var hasComma = format.indexOf(comma) != -1,
9561                 psplit   = (i18n ? format.replace(/[^\d\,]/g, '') : format.replace(/[^\d\.]/g, '')).split(dec);
9562
9563             if (1 < psplit.length) {
9564                 v = v.toFixed(psplit[1].length);
9565             } else if(2 < psplit.length) {
9566                 throw ('NumberFormatException: invalid format, formats should have no more than 1 period: ' + format);
9567             } else {
9568                 v = v.toFixed(0);
9569             }
9570
9571             var fnum = v.toString();
9572
9573             psplit = fnum.split('.');
9574
9575             if (hasComma) {
9576                 var cnum = psplit[0], 
9577                     parr = [], 
9578                     j    = cnum.length, 
9579                     m    = Math.floor(j / 3),
9580                     n    = cnum.length % 3 || 3,
9581                     i;
9582
9583                 for (i = 0; i < j; i += n) {
9584                     if (i != 0) {
9585                         n = 3;
9586                     }
9587                     
9588                     parr[parr.length] = cnum.substr(i, n);
9589                     m -= 1;
9590                 }
9591                 fnum = parr.join(comma);
9592                 if (psplit[1]) {
9593                     fnum += dec + psplit[1];
9594                 }
9595             } else {
9596                 if (psplit[1]) {
9597                     fnum = psplit[0] + dec + psplit[1];
9598                 }
9599             }
9600
9601             return (neg ? '-' : '') + format.replace(/[\d,?\.?]+/, fnum);
9602         },
9603
9604         
9605         numberRenderer : function(format) {
9606             return function(v) {
9607                 return Ext.util.Format.number(v, format);
9608             };
9609         },
9610
9611         
9612         plural : function(v, s, p) {
9613             return v +' ' + (v == 1 ? s : (p ? p : s+'s'));
9614         },
9615
9616         
9617         nl2br : function(v) {
9618             return Ext.isEmpty(v) ? '' : v.replace(nl2brRe, '<br/>');
9619         }
9620     };
9621 }();
9622
9623 Ext.XTemplate = function(){
9624     Ext.XTemplate.superclass.constructor.apply(this, arguments);
9625
9626     var me = this,
9627         s = me.html,
9628         re = /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/,
9629         nameRe = /^<tpl\b[^>]*?for="(.*?)"/,
9630         ifRe = /^<tpl\b[^>]*?if="(.*?)"/,
9631         execRe = /^<tpl\b[^>]*?exec="(.*?)"/,
9632         m,
9633         id = 0,
9634         tpls = [],
9635         VALUES = 'values',
9636         PARENT = 'parent',
9637         XINDEX = 'xindex',
9638         XCOUNT = 'xcount',
9639         RETURN = 'return ',
9640         WITHVALUES = 'with(values){ ';
9641
9642     s = ['<tpl>', s, '</tpl>'].join('');
9643
9644     while((m = s.match(re))){
9645         var m2 = m[0].match(nameRe),
9646             m3 = m[0].match(ifRe),
9647             m4 = m[0].match(execRe),
9648             exp = null,
9649             fn = null,
9650             exec = null,
9651             name = m2 && m2[1] ? m2[1] : '';
9652
9653        if (m3) {
9654            exp = m3 && m3[1] ? m3[1] : null;
9655            if(exp){
9656                fn = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + RETURN +(Ext.util.Format.htmlDecode(exp))+'; }');
9657            }
9658        }
9659        if (m4) {
9660            exp = m4 && m4[1] ? m4[1] : null;
9661            if(exp){
9662                exec = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES +(Ext.util.Format.htmlDecode(exp))+'; }');
9663            }
9664        }
9665        if(name){
9666            switch(name){
9667                case '.': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + VALUES + '; }'); break;
9668                case '..': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + PARENT + '; }'); break;
9669                default: name = new Function(VALUES, PARENT, WITHVALUES + RETURN + name + '; }');
9670            }
9671        }
9672        tpls.push({
9673             id: id,
9674             target: name,
9675             exec: exec,
9676             test: fn,
9677             body: m[1]||''
9678         });
9679        s = s.replace(m[0], '{xtpl'+ id + '}');
9680        ++id;
9681     }
9682     for(var i = tpls.length-1; i >= 0; --i){
9683         me.compileTpl(tpls[i]);
9684     }
9685     me.master = tpls[tpls.length-1];
9686     me.tpls = tpls;
9687 };
9688 Ext.extend(Ext.XTemplate, Ext.Template, {
9689     
9690     re : /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\\]\s?[\d\.\+\-\*\\\(\)]+)?\}/g,
9691     
9692     codeRe : /\{\[((?:\\\]|.|\n)*?)\]\}/g,
9693
9694     
9695     applySubTemplate : function(id, values, parent, xindex, xcount){
9696         var me = this,
9697             len,
9698             t = me.tpls[id],
9699             vs,
9700             buf = [];
9701         if ((t.test && !t.test.call(me, values, parent, xindex, xcount)) ||
9702             (t.exec && t.exec.call(me, values, parent, xindex, xcount))) {
9703             return '';
9704         }
9705         vs = t.target ? t.target.call(me, values, parent) : values;
9706         len = vs.length;
9707         parent = t.target ? values : parent;
9708         if(t.target && Ext.isArray(vs)){
9709             for(var i = 0, len = vs.length; i < len; i++){
9710                 buf[buf.length] = t.compiled.call(me, vs[i], parent, i+1, len);
9711             }
9712             return buf.join('');
9713         }
9714         return t.compiled.call(me, vs, parent, xindex, xcount);
9715     },
9716
9717     
9718     compileTpl : function(tpl){
9719         var fm = Ext.util.Format,
9720             useF = this.disableFormats !== true,
9721             sep = Ext.isGecko ? "+" : ",",
9722             body;
9723
9724         function fn(m, name, format, args, math){
9725             if(name.substr(0, 4) == 'xtpl'){
9726                 return "'"+ sep +'this.applySubTemplate('+name.substr(4)+', values, parent, xindex, xcount)'+sep+"'";
9727             }
9728             var v;
9729             if(name === '.'){
9730                 v = 'values';
9731             }else if(name === '#'){
9732                 v = 'xindex';
9733             }else if(name.indexOf('.') != -1){
9734                 v = name;
9735             }else{
9736                 v = "values['" + name + "']";
9737             }
9738             if(math){
9739                 v = '(' + v + math + ')';
9740             }
9741             if (format && useF) {
9742                 args = args ? ',' + args : "";
9743                 if(format.substr(0, 5) != "this."){
9744                     format = "fm." + format + '(';
9745                 }else{
9746                     format = 'this.call("'+ format.substr(5) + '", ';
9747                     args = ", values";
9748                 }
9749             } else {
9750                 args= ''; format = "("+v+" === undefined ? '' : ";
9751             }
9752             return "'"+ sep + format + v + args + ")"+sep+"'";
9753         }
9754
9755         function codeFn(m, code){
9756             
9757             return "'" + sep + '(' + code.replace(/\\'/g, "'") + ')' + sep + "'";
9758         }
9759
9760         
9761         if(Ext.isGecko){
9762             body = "tpl.compiled = function(values, parent, xindex, xcount){ return '" +
9763                    tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn) +
9764                     "';};";
9765         }else{
9766             body = ["tpl.compiled = function(values, parent, xindex, xcount){ return ['"];
9767             body.push(tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn));
9768             body.push("'].join('');};");
9769             body = body.join('');
9770         }
9771         eval(body);
9772         return this;
9773     },
9774
9775     
9776     applyTemplate : function(values){
9777         return this.master.compiled.call(this, values, {}, 1, 1);
9778     },
9779
9780     
9781     compile : function(){return this;}
9782
9783     
9784     
9785     
9786
9787 });
9788
9789 Ext.XTemplate.prototype.apply = Ext.XTemplate.prototype.applyTemplate;
9790
9791
9792 Ext.XTemplate.from = function(el){
9793     el = Ext.getDom(el);
9794     return new Ext.XTemplate(el.value || el.innerHTML);
9795 };
9796
9797 Ext.util.CSS = function(){
9798         var rules = null;
9799         var doc = document;
9800
9801     var camelRe = /(-[a-z])/gi;
9802     var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
9803
9804    return {
9805    
9806    createStyleSheet : function(cssText, id){
9807        var ss;
9808        var head = doc.getElementsByTagName("head")[0];
9809        var rules = doc.createElement("style");
9810        rules.setAttribute("type", "text/css");
9811        if(id){
9812            rules.setAttribute("id", id);
9813        }
9814        if(Ext.isIE){
9815            head.appendChild(rules);
9816            ss = rules.styleSheet;
9817            ss.cssText = cssText;
9818        }else{
9819            try{
9820                 rules.appendChild(doc.createTextNode(cssText));
9821            }catch(e){
9822                rules.cssText = cssText;
9823            }
9824            head.appendChild(rules);
9825            ss = rules.styleSheet ? rules.styleSheet : (rules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
9826        }
9827        this.cacheStyleSheet(ss);
9828        return ss;
9829    },
9830
9831    
9832    removeStyleSheet : function(id){
9833        var existing = doc.getElementById(id);
9834        if(existing){
9835            existing.parentNode.removeChild(existing);
9836        }
9837    },
9838
9839    
9840    swapStyleSheet : function(id, url){
9841        this.removeStyleSheet(id);
9842        var ss = doc.createElement("link");
9843        ss.setAttribute("rel", "stylesheet");
9844        ss.setAttribute("type", "text/css");
9845        ss.setAttribute("id", id);
9846        ss.setAttribute("href", url);
9847        doc.getElementsByTagName("head")[0].appendChild(ss);
9848    },
9849    
9850    
9851    refreshCache : function(){
9852        return this.getRules(true);
9853    },
9854
9855    
9856    cacheStyleSheet : function(ss){
9857        if(!rules){
9858            rules = {};
9859        }
9860        try{
9861            var ssRules = ss.cssRules || ss.rules;
9862            for(var j = ssRules.length-1; j >= 0; --j){
9863                rules[ssRules[j].selectorText.toLowerCase()] = ssRules[j];
9864            }
9865        }catch(e){}
9866    },
9867    
9868    
9869    getRules : function(refreshCache){
9870                 if(rules === null || refreshCache){
9871                         rules = {};
9872                         var ds = doc.styleSheets;
9873                         for(var i =0, len = ds.length; i < len; i++){
9874                             try{
9875                         this.cacheStyleSheet(ds[i]);
9876                     }catch(e){} 
9877                 }
9878                 }
9879                 return rules;
9880         },
9881         
9882         
9883    getRule : function(selector, refreshCache){
9884                 var rs = this.getRules(refreshCache);
9885                 if(!Ext.isArray(selector)){
9886                     return rs[selector.toLowerCase()];
9887                 }
9888                 for(var i = 0; i < selector.length; i++){
9889                         if(rs[selector[i]]){
9890                                 return rs[selector[i].toLowerCase()];
9891                         }
9892                 }
9893                 return null;
9894         },
9895         
9896         
9897         
9898    updateRule : function(selector, property, value){
9899                 if(!Ext.isArray(selector)){
9900                         var rule = this.getRule(selector);
9901                         if(rule){
9902                                 rule.style[property.replace(camelRe, camelFn)] = value;
9903                                 return true;
9904                         }
9905                 }else{
9906                         for(var i = 0; i < selector.length; i++){
9907                                 if(this.updateRule(selector[i], property, value)){
9908                                         return true;
9909                                 }
9910                         }
9911                 }
9912                 return false;
9913         }
9914    };   
9915 }();
9916 Ext.util.ClickRepeater = Ext.extend(Ext.util.Observable, {
9917     
9918     constructor : function(el, config){
9919         this.el = Ext.get(el);
9920         this.el.unselectable();
9921
9922         Ext.apply(this, config);
9923
9924         this.addEvents(
9925         
9926         "mousedown",
9927         
9928         "click",
9929         
9930         "mouseup"
9931         );
9932
9933         if(!this.disabled){
9934             this.disabled = true;
9935             this.enable();
9936         }
9937
9938         
9939         if(this.handler){
9940             this.on("click", this.handler,  this.scope || this);
9941         }
9942
9943         Ext.util.ClickRepeater.superclass.constructor.call(this);        
9944     },
9945     
9946     interval : 20,
9947     delay: 250,
9948     preventDefault : true,
9949     stopDefault : false,
9950     timer : 0,
9951
9952     
9953     enable: function(){
9954         if(this.disabled){
9955             this.el.on('mousedown', this.handleMouseDown, this);
9956             if (Ext.isIE){
9957                 this.el.on('dblclick', this.handleDblClick, this);
9958             }
9959             if(this.preventDefault || this.stopDefault){
9960                 this.el.on('click', this.eventOptions, this);
9961             }
9962         }
9963         this.disabled = false;
9964     },
9965
9966     
9967     disable: function( force){
9968         if(force || !this.disabled){
9969             clearTimeout(this.timer);
9970             if(this.pressClass){
9971                 this.el.removeClass(this.pressClass);
9972             }
9973             Ext.getDoc().un('mouseup', this.handleMouseUp, this);
9974             this.el.removeAllListeners();
9975         }
9976         this.disabled = true;
9977     },
9978
9979     
9980     setDisabled: function(disabled){
9981         this[disabled ? 'disable' : 'enable']();
9982     },
9983
9984     eventOptions: function(e){
9985         if(this.preventDefault){
9986             e.preventDefault();
9987         }
9988         if(this.stopDefault){
9989             e.stopEvent();
9990         }
9991     },
9992
9993     
9994     destroy : function() {
9995         this.disable(true);
9996         Ext.destroy(this.el);
9997         this.purgeListeners();
9998     },
9999
10000     handleDblClick : function(e){
10001         clearTimeout(this.timer);
10002         this.el.blur();
10003
10004         this.fireEvent("mousedown", this, e);
10005         this.fireEvent("click", this, e);
10006     },
10007
10008     
10009     handleMouseDown : function(e){
10010         clearTimeout(this.timer);
10011         this.el.blur();
10012         if(this.pressClass){
10013             this.el.addClass(this.pressClass);
10014         }
10015         this.mousedownTime = new Date();
10016
10017         Ext.getDoc().on("mouseup", this.handleMouseUp, this);
10018         this.el.on("mouseout", this.handleMouseOut, this);
10019
10020         this.fireEvent("mousedown", this, e);
10021         this.fireEvent("click", this, e);
10022
10023         
10024         if (this.accelerate) {
10025             this.delay = 400;
10026         }
10027         this.timer = this.click.defer(this.delay || this.interval, this, [e]);
10028     },
10029
10030     
10031     click : function(e){
10032         this.fireEvent("click", this, e);
10033         this.timer = this.click.defer(this.accelerate ?
10034             this.easeOutExpo(this.mousedownTime.getElapsed(),
10035                 400,
10036                 -390,
10037                 12000) :
10038             this.interval, this, [e]);
10039     },
10040
10041     easeOutExpo : function (t, b, c, d) {
10042         return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
10043     },
10044
10045     
10046     handleMouseOut : function(){
10047         clearTimeout(this.timer);
10048         if(this.pressClass){
10049             this.el.removeClass(this.pressClass);
10050         }
10051         this.el.on("mouseover", this.handleMouseReturn, this);
10052     },
10053
10054     
10055     handleMouseReturn : function(){
10056         this.el.un("mouseover", this.handleMouseReturn, this);
10057         if(this.pressClass){
10058             this.el.addClass(this.pressClass);
10059         }
10060         this.click();
10061     },
10062
10063     
10064     handleMouseUp : function(e){
10065         clearTimeout(this.timer);
10066         this.el.un("mouseover", this.handleMouseReturn, this);
10067         this.el.un("mouseout", this.handleMouseOut, this);
10068         Ext.getDoc().un("mouseup", this.handleMouseUp, this);
10069         this.el.removeClass(this.pressClass);
10070         this.fireEvent("mouseup", this, e);
10071     }
10072 });
10073 Ext.KeyNav = function(el, config){
10074     this.el = Ext.get(el);
10075     Ext.apply(this, config);
10076     if(!this.disabled){
10077         this.disabled = true;
10078         this.enable();
10079     }
10080 };
10081
10082 Ext.KeyNav.prototype = {
10083     
10084     disabled : false,
10085     
10086     defaultEventAction: "stopEvent",
10087     
10088     forceKeyDown : false,
10089
10090     
10091     relay : function(e){
10092         var k = e.getKey(),
10093             h = this.keyToHandler[k];
10094         if(h && this[h]){
10095             if(this.doRelay(e, this[h], h) !== true){
10096                 e[this.defaultEventAction]();
10097             }
10098         }
10099     },
10100
10101     
10102     doRelay : function(e, h, hname){
10103         return h.call(this.scope || this, e, hname);
10104     },
10105
10106     
10107     enter : false,
10108     left : false,
10109     right : false,
10110     up : false,
10111     down : false,
10112     tab : false,
10113     esc : false,
10114     pageUp : false,
10115     pageDown : false,
10116     del : false,
10117     home : false,
10118     end : false,
10119
10120     
10121     keyToHandler : {
10122         37 : "left",
10123         39 : "right",
10124         38 : "up",
10125         40 : "down",
10126         33 : "pageUp",
10127         34 : "pageDown",
10128         46 : "del",
10129         36 : "home",
10130         35 : "end",
10131         13 : "enter",
10132         27 : "esc",
10133         9  : "tab"
10134     },
10135     
10136     stopKeyUp: function(e) {
10137         var k = e.getKey();
10138
10139         if (k >= 37 && k <= 40) {
10140             
10141             
10142             e.stopEvent();
10143         }
10144     },
10145     
10146     
10147     destroy: function(){
10148         this.disable();    
10149     },
10150
10151         
10152         enable: function() {
10153         if (this.disabled) {
10154             if (Ext.isSafari2) {
10155                 
10156                 this.el.on('keyup', this.stopKeyUp, this);
10157             }
10158
10159             this.el.on(this.isKeydown()? 'keydown' : 'keypress', this.relay, this);
10160             this.disabled = false;
10161         }
10162     },
10163
10164         
10165         disable: function() {
10166         if (!this.disabled) {
10167             if (Ext.isSafari2) {
10168                 
10169                 this.el.un('keyup', this.stopKeyUp, this);
10170             }
10171
10172             this.el.un(this.isKeydown()? 'keydown' : 'keypress', this.relay, this);
10173             this.disabled = true;
10174         }
10175     },
10176     
10177     
10178     setDisabled : function(disabled){
10179         this[disabled ? "disable" : "enable"]();
10180     },
10181     
10182     
10183     isKeydown: function(){
10184         return this.forceKeyDown || Ext.EventManager.useKeydown;
10185     }
10186 };
10187
10188 Ext.KeyMap = function(el, config, eventName){
10189     this.el  = Ext.get(el);
10190     this.eventName = eventName || "keydown";
10191     this.bindings = [];
10192     if(config){
10193         this.addBinding(config);
10194     }
10195     this.enable();
10196 };
10197
10198 Ext.KeyMap.prototype = {
10199     
10200     stopEvent : false,
10201
10202     
10203         addBinding : function(config){
10204         if(Ext.isArray(config)){
10205             Ext.each(config, function(c){
10206                 this.addBinding(c);
10207             }, this);
10208             return;
10209         }
10210         var keyCode = config.key,
10211             fn = config.fn || config.handler,
10212             scope = config.scope;
10213
10214         if (config.stopEvent) {
10215             this.stopEvent = config.stopEvent;    
10216         }       
10217
10218         if(typeof keyCode == "string"){
10219             var ks = [];
10220             var keyString = keyCode.toUpperCase();
10221             for(var j = 0, len = keyString.length; j < len; j++){
10222                 ks.push(keyString.charCodeAt(j));
10223             }
10224             keyCode = ks;
10225         }
10226         var keyArray = Ext.isArray(keyCode);
10227         
10228         var handler = function(e){
10229             if(this.checkModifiers(config, e)){
10230                 var k = e.getKey();
10231                 if(keyArray){
10232                     for(var i = 0, len = keyCode.length; i < len; i++){
10233                         if(keyCode[i] == k){
10234                           if(this.stopEvent){
10235                               e.stopEvent();
10236                           }
10237                           fn.call(scope || window, k, e);
10238                           return;
10239                         }
10240                     }
10241                 }else{
10242                     if(k == keyCode){
10243                         if(this.stopEvent){
10244                            e.stopEvent();
10245                         }
10246                         fn.call(scope || window, k, e);
10247                     }
10248                 }
10249             }
10250         };
10251         this.bindings.push(handler);
10252         },
10253     
10254     
10255     checkModifiers: function(config, e){
10256         var val, key, keys = ['shift', 'ctrl', 'alt'];
10257         for (var i = 0, len = keys.length; i < len; ++i){
10258             key = keys[i];
10259             val = config[key];
10260             if(!(val === undefined || (val === e[key + 'Key']))){
10261                 return false;
10262             }
10263         }
10264         return true;
10265     },
10266
10267     
10268     on : function(key, fn, scope){
10269         var keyCode, shift, ctrl, alt;
10270         if(typeof key == "object" && !Ext.isArray(key)){
10271             keyCode = key.key;
10272             shift = key.shift;
10273             ctrl = key.ctrl;
10274             alt = key.alt;
10275         }else{
10276             keyCode = key;
10277         }
10278         this.addBinding({
10279             key: keyCode,
10280             shift: shift,
10281             ctrl: ctrl,
10282             alt: alt,
10283             fn: fn,
10284             scope: scope
10285         });
10286     },
10287
10288     
10289     handleKeyDown : function(e){
10290             if(this.enabled){ 
10291             var b = this.bindings;
10292             for(var i = 0, len = b.length; i < len; i++){
10293                 b[i].call(this, e);
10294             }
10295             }
10296         },
10297
10298         
10299         isEnabled : function(){
10300             return this.enabled;
10301         },
10302
10303         
10304         enable: function(){
10305                 if(!this.enabled){
10306                     this.el.on(this.eventName, this.handleKeyDown, this);
10307                     this.enabled = true;
10308                 }
10309         },
10310
10311         
10312         disable: function(){
10313                 if(this.enabled){
10314                     this.el.removeListener(this.eventName, this.handleKeyDown, this);
10315                     this.enabled = false;
10316                 }
10317         },
10318     
10319     
10320     setDisabled : function(disabled){
10321         this[disabled ? "disable" : "enable"]();
10322     }
10323 };
10324 Ext.util.TextMetrics = function(){
10325     var shared;
10326     return {
10327         
10328         measure : function(el, text, fixedWidth){
10329             if(!shared){
10330                 shared = Ext.util.TextMetrics.Instance(el, fixedWidth);
10331             }
10332             shared.bind(el);
10333             shared.setFixedWidth(fixedWidth || 'auto');
10334             return shared.getSize(text);
10335         },
10336
10337         
10338         createInstance : function(el, fixedWidth){
10339             return Ext.util.TextMetrics.Instance(el, fixedWidth);
10340         }
10341     };
10342 }();
10343
10344 Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth){
10345     var ml = new Ext.Element(document.createElement('div'));
10346     document.body.appendChild(ml.dom);
10347     ml.position('absolute');
10348     ml.setLeftTop(-1000, -1000);
10349     ml.hide();
10350
10351     if(fixedWidth){
10352         ml.setWidth(fixedWidth);
10353     }
10354
10355     var instance = {
10356         
10357         getSize : function(text){
10358             ml.update(text);
10359             var s = ml.getSize();
10360             ml.update('');
10361             return s;
10362         },
10363
10364         
10365         bind : function(el){
10366             ml.setStyle(
10367                 Ext.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing')
10368             );
10369         },
10370
10371         
10372         setFixedWidth : function(width){
10373             ml.setWidth(width);
10374         },
10375
10376         
10377         getWidth : function(text){
10378             ml.dom.style.width = 'auto';
10379             return this.getSize(text).width;
10380         },
10381
10382         
10383         getHeight : function(text){
10384             return this.getSize(text).height;
10385         }
10386     };
10387
10388     instance.bind(bindTo);
10389
10390     return instance;
10391 };
10392
10393 Ext.Element.addMethods({
10394     
10395     getTextWidth : function(text, min, max){
10396         return (Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width).constrain(min || 0, max || 1000000);
10397     }
10398 });
10399
10400 Ext.util.Cookies = {
10401     
10402     set : function(name, value){
10403         var argv = arguments;
10404         var argc = arguments.length;
10405         var expires = (argc > 2) ? argv[2] : null;
10406         var path = (argc > 3) ? argv[3] : '/';
10407         var domain = (argc > 4) ? argv[4] : null;
10408         var secure = (argc > 5) ? argv[5] : false;
10409         document.cookie = name + "=" + escape(value) + ((expires === null) ? "" : ("; expires=" + expires.toGMTString())) + ((path === null) ? "" : ("; path=" + path)) + ((domain === null) ? "" : ("; domain=" + domain)) + ((secure === true) ? "; secure" : "");
10410     },
10411
10412     
10413     get : function(name){
10414         var arg = name + "=";
10415         var alen = arg.length;
10416         var clen = document.cookie.length;
10417         var i = 0;
10418         var j = 0;
10419         while(i < clen){
10420             j = i + alen;
10421             if(document.cookie.substring(i, j) == arg){
10422                 return Ext.util.Cookies.getCookieVal(j);
10423             }
10424             i = document.cookie.indexOf(" ", i) + 1;
10425             if(i === 0){
10426                 break;
10427             }
10428         }
10429         return null;
10430     },
10431
10432     
10433     clear : function(name){
10434         if(Ext.util.Cookies.get(name)){
10435             document.cookie = name + "=" + "; expires=Thu, 01-Jan-70 00:00:01 GMT";
10436         }
10437     },
10438     
10439     getCookieVal : function(offset){
10440         var endstr = document.cookie.indexOf(";", offset);
10441         if(endstr == -1){
10442             endstr = document.cookie.length;
10443         }
10444         return unescape(document.cookie.substring(offset, endstr));
10445     }
10446 };
10447 Ext.handleError = function(e) {
10448     throw e;
10449 };
10450
10451
10452 Ext.Error = function(message) {
10453     
10454     this.message = (this.lang[message]) ? this.lang[message] : message;
10455 };
10456
10457 Ext.Error.prototype = new Error();
10458 Ext.apply(Ext.Error.prototype, {
10459     
10460     lang: {},
10461
10462     name: 'Ext.Error',
10463     
10464     getName : function() {
10465         return this.name;
10466     },
10467     
10468     getMessage : function() {
10469         return this.message;
10470     },
10471     
10472     toJson : function() {
10473         return Ext.encode(this);
10474     }
10475 });
10476
10477 Ext.ComponentMgr = function(){
10478     var all = new Ext.util.MixedCollection();
10479     var types = {};
10480     var ptypes = {};
10481
10482     return {
10483         
10484         register : function(c){
10485             all.add(c);
10486         },
10487
10488         
10489         unregister : function(c){
10490             all.remove(c);
10491         },
10492
10493         
10494         get : function(id){
10495             return all.get(id);
10496         },
10497
10498         
10499         onAvailable : function(id, fn, scope){
10500             all.on("add", function(index, o){
10501                 if(o.id == id){
10502                     fn.call(scope || o, o);
10503                     all.un("add", fn, scope);
10504                 }
10505             });
10506         },
10507
10508         
10509         all : all,
10510         
10511         
10512         types : types,
10513         
10514         
10515         ptypes: ptypes,
10516         
10517         
10518         isRegistered : function(xtype){
10519             return types[xtype] !== undefined;    
10520         },
10521         
10522         
10523         isPluginRegistered : function(ptype){
10524             return ptypes[ptype] !== undefined;    
10525         },        
10526
10527         
10528         registerType : function(xtype, cls){
10529             types[xtype] = cls;
10530             cls.xtype = xtype;
10531         },
10532
10533         
10534         create : function(config, defaultType){
10535             return config.render ? config : new types[config.xtype || defaultType](config);
10536         },
10537
10538         
10539         registerPlugin : function(ptype, cls){
10540             ptypes[ptype] = cls;
10541             cls.ptype = ptype;
10542         },
10543
10544         
10545         createPlugin : function(config, defaultType){
10546             var PluginCls = ptypes[config.ptype || defaultType];
10547             if (PluginCls.init) {
10548                 return PluginCls;                
10549             } else {
10550                 return new PluginCls(config);
10551             }            
10552         }
10553     };
10554 }();
10555
10556
10557 Ext.reg = Ext.ComponentMgr.registerType; 
10558
10559 Ext.preg = Ext.ComponentMgr.registerPlugin;
10560
10561 Ext.create = Ext.ComponentMgr.create;
10562 Ext.Component = function(config){
10563     config = config || {};
10564     if(config.initialConfig){
10565         if(config.isAction){           
10566             this.baseAction = config;
10567         }
10568         config = config.initialConfig; 
10569     }else if(config.tagName || config.dom || Ext.isString(config)){ 
10570         config = {applyTo: config, id: config.id || config};
10571     }
10572
10573     
10574     this.initialConfig = config;
10575
10576     Ext.apply(this, config);
10577     this.addEvents(
10578         
10579         'added',
10580         
10581         'disable',
10582         
10583         'enable',
10584         
10585         'beforeshow',
10586         
10587         'show',
10588         
10589         'beforehide',
10590         
10591         'hide',
10592         
10593         'removed',
10594         
10595         'beforerender',
10596         
10597         'render',
10598         
10599         'afterrender',
10600         
10601         'beforedestroy',
10602         
10603         'destroy',
10604         
10605         'beforestaterestore',
10606         
10607         'staterestore',
10608         
10609         'beforestatesave',
10610         
10611         'statesave'
10612     );
10613     this.getId();
10614     Ext.ComponentMgr.register(this);
10615     Ext.Component.superclass.constructor.call(this);
10616
10617     if(this.baseAction){
10618         this.baseAction.addComponent(this);
10619     }
10620
10621     this.initComponent();
10622
10623     if(this.plugins){
10624         if(Ext.isArray(this.plugins)){
10625             for(var i = 0, len = this.plugins.length; i < len; i++){
10626                 this.plugins[i] = this.initPlugin(this.plugins[i]);
10627             }
10628         }else{
10629             this.plugins = this.initPlugin(this.plugins);
10630         }
10631     }
10632
10633     if(this.stateful !== false){
10634         this.initState();
10635     }
10636
10637     if(this.applyTo){
10638         this.applyToMarkup(this.applyTo);
10639         delete this.applyTo;
10640     }else if(this.renderTo){
10641         this.render(this.renderTo);
10642         delete this.renderTo;
10643     }
10644 };
10645
10646
10647 Ext.Component.AUTO_ID = 1000;
10648
10649 Ext.extend(Ext.Component, Ext.util.Observable, {
10650     
10651     
10652     
10653     
10654     
10655     
10656     
10657
10658     
10659     
10660     
10661     
10662     
10663     
10664     
10665     
10666     
10667     disabled : false,
10668     
10669     hidden : false,
10670     
10671     
10672     
10673     
10674     
10675     
10676     
10677     autoEl : 'div',
10678
10679     
10680     disabledClass : 'x-item-disabled',
10681     
10682     allowDomMove : true,
10683     
10684     autoShow : false,
10685     
10686     hideMode : 'display',
10687     
10688     hideParent : false,
10689     
10690     
10691     
10692     
10693     
10694     rendered : false,
10695
10696     
10697     
10698
10699     
10700
10701     
10702     tplWriteMode : 'overwrite',
10703
10704     
10705     
10706     
10707     bubbleEvents: [],
10708
10709
10710     
10711     ctype : 'Ext.Component',
10712
10713     
10714     actionMode : 'el',
10715
10716     
10717     getActionEl : function(){
10718         return this[this.actionMode];
10719     },
10720
10721     initPlugin : function(p){
10722         if(p.ptype && !Ext.isFunction(p.init)){
10723             p = Ext.ComponentMgr.createPlugin(p);
10724         }else if(Ext.isString(p)){
10725             p = Ext.ComponentMgr.createPlugin({
10726                 ptype: p
10727             });
10728         }
10729         p.init(this);
10730         return p;
10731     },
10732
10733     
10734     initComponent : function(){
10735         
10736         if(this.listeners){
10737             this.on(this.listeners);
10738             delete this.listeners;
10739         }
10740         this.enableBubble(this.bubbleEvents);
10741     },
10742
10743     
10744     render : function(container, position){
10745         if(!this.rendered && this.fireEvent('beforerender', this) !== false){
10746             if(!container && this.el){
10747                 this.el = Ext.get(this.el);
10748                 container = this.el.dom.parentNode;
10749                 this.allowDomMove = false;
10750             }
10751             this.container = Ext.get(container);
10752             if(this.ctCls){
10753                 this.container.addClass(this.ctCls);
10754             }
10755             this.rendered = true;
10756             if(position !== undefined){
10757                 if(Ext.isNumber(position)){
10758                     position = this.container.dom.childNodes[position];
10759                 }else{
10760                     position = Ext.getDom(position);
10761                 }
10762             }
10763             this.onRender(this.container, position || null);
10764             if(this.autoShow){
10765                 this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);
10766             }
10767             if(this.cls){
10768                 this.el.addClass(this.cls);
10769                 delete this.cls;
10770             }
10771             if(this.style){
10772                 this.el.applyStyles(this.style);
10773                 delete this.style;
10774             }
10775             if(this.overCls){
10776                 this.el.addClassOnOver(this.overCls);
10777             }
10778             this.fireEvent('render', this);
10779
10780
10781             
10782             
10783             var contentTarget = this.getContentTarget();
10784             if (this.html){
10785                 contentTarget.update(Ext.DomHelper.markup(this.html));
10786                 delete this.html;
10787             }
10788             if (this.contentEl){
10789                 var ce = Ext.getDom(this.contentEl);
10790                 Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
10791                 contentTarget.appendChild(ce);
10792             }
10793             if (this.tpl) {
10794                 if (!this.tpl.compile) {
10795                     this.tpl = new Ext.XTemplate(this.tpl);
10796                 }
10797                 if (this.data) {
10798                     this.tpl[this.tplWriteMode](contentTarget, this.data);
10799                     delete this.data;
10800                 }
10801             }
10802             this.afterRender(this.container);
10803
10804
10805             if(this.hidden){
10806                 
10807                 this.doHide();
10808             }
10809             if(this.disabled){
10810                 
10811                 this.disable(true);
10812             }
10813
10814             if(this.stateful !== false){
10815                 this.initStateEvents();
10816             }
10817             this.fireEvent('afterrender', this);
10818         }
10819         return this;
10820     },
10821
10822
10823     
10824     update: function(htmlOrData, loadScripts, cb) {
10825         var contentTarget = this.getContentTarget();
10826         if (this.tpl && typeof htmlOrData !== "string") {
10827             this.tpl[this.tplWriteMode](contentTarget, htmlOrData || {});
10828         } else {
10829             var html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
10830             contentTarget.update(html, loadScripts, cb);
10831         }
10832     },
10833
10834
10835     
10836     onAdded : function(container, pos) {
10837         this.ownerCt = container;
10838         this.initRef();
10839         this.fireEvent('added', this, container, pos);
10840     },
10841
10842     
10843     onRemoved : function() {
10844         this.removeRef();
10845         this.fireEvent('removed', this, this.ownerCt);
10846         delete this.ownerCt;
10847     },
10848
10849     
10850     initRef : function() {
10851         
10852         if(this.ref && !this.refOwner){
10853             var levels = this.ref.split('/'),
10854                 last = levels.length,
10855                 i = 0,
10856                 t = this;
10857
10858             while(t && i < last){
10859                 t = t.ownerCt;
10860                 ++i;
10861             }
10862             if(t){
10863                 t[this.refName = levels[--i]] = this;
10864                 
10865                 this.refOwner = t;
10866             }
10867         }
10868     },
10869
10870     removeRef : function() {
10871         if (this.refOwner && this.refName) {
10872             delete this.refOwner[this.refName];
10873             delete this.refOwner;
10874         }
10875     },
10876
10877     
10878     initState : function(){
10879         if(Ext.state.Manager){
10880             var id = this.getStateId();
10881             if(id){
10882                 var state = Ext.state.Manager.get(id);
10883                 if(state){
10884                     if(this.fireEvent('beforestaterestore', this, state) !== false){
10885                         this.applyState(Ext.apply({}, state));
10886                         this.fireEvent('staterestore', this, state);
10887                     }
10888                 }
10889             }
10890         }
10891     },
10892
10893     
10894     getStateId : function(){
10895         return this.stateId || ((/^(ext-comp-|ext-gen)/).test(String(this.id)) ? null : this.id);
10896     },
10897
10898     
10899     initStateEvents : function(){
10900         if(this.stateEvents){
10901             for(var i = 0, e; e = this.stateEvents[i]; i++){
10902                 this.on(e, this.saveState, this, {delay:100});
10903             }
10904         }
10905     },
10906
10907     
10908     applyState : function(state){
10909         if(state){
10910             Ext.apply(this, state);
10911         }
10912     },
10913
10914     
10915     getState : function(){
10916         return null;
10917     },
10918
10919     
10920     saveState : function(){
10921         if(Ext.state.Manager && this.stateful !== false){
10922             var id = this.getStateId();
10923             if(id){
10924                 var state = this.getState();
10925                 if(this.fireEvent('beforestatesave', this, state) !== false){
10926                     Ext.state.Manager.set(id, state);
10927                     this.fireEvent('statesave', this, state);
10928                 }
10929             }
10930         }
10931     },
10932
10933     
10934     applyToMarkup : function(el){
10935         this.allowDomMove = false;
10936         this.el = Ext.get(el);
10937         this.render(this.el.dom.parentNode);
10938     },
10939
10940     
10941     addClass : function(cls){
10942         if(this.el){
10943             this.el.addClass(cls);
10944         }else{
10945             this.cls = this.cls ? this.cls + ' ' + cls : cls;
10946         }
10947         return this;
10948     },
10949
10950     
10951     removeClass : function(cls){
10952         if(this.el){
10953             this.el.removeClass(cls);
10954         }else if(this.cls){
10955             this.cls = this.cls.split(' ').remove(cls).join(' ');
10956         }
10957         return this;
10958     },
10959
10960     
10961     
10962     onRender : function(ct, position){
10963         if(!this.el && this.autoEl){
10964             if(Ext.isString(this.autoEl)){
10965                 this.el = document.createElement(this.autoEl);
10966             }else{
10967                 var div = document.createElement('div');
10968                 Ext.DomHelper.overwrite(div, this.autoEl);
10969                 this.el = div.firstChild;
10970             }
10971             if (!this.el.id) {
10972                 this.el.id = this.getId();
10973             }
10974         }
10975         if(this.el){
10976             this.el = Ext.get(this.el);
10977             if(this.allowDomMove !== false){
10978                 ct.dom.insertBefore(this.el.dom, position);
10979                 if (div) {
10980                     Ext.removeNode(div);
10981                     div = null;
10982                 }
10983             }
10984         }
10985     },
10986
10987     
10988     getAutoCreate : function(){
10989         var cfg = Ext.isObject(this.autoCreate) ?
10990                       this.autoCreate : Ext.apply({}, this.defaultAutoCreate);
10991         if(this.id && !cfg.id){
10992             cfg.id = this.id;
10993         }
10994         return cfg;
10995     },
10996
10997     
10998     afterRender : Ext.emptyFn,
10999
11000     
11001     destroy : function(){
11002         if(!this.isDestroyed){
11003             if(this.fireEvent('beforedestroy', this) !== false){
11004                 this.destroying = true;
11005                 this.beforeDestroy();
11006                 if(this.ownerCt && this.ownerCt.remove){
11007                     this.ownerCt.remove(this, false);
11008                 }
11009                 if(this.rendered){
11010                     this.el.remove();
11011                     if(this.actionMode == 'container' || this.removeMode == 'container'){
11012                         this.container.remove();
11013                     }
11014                 }
11015                 
11016                 if(this.focusTask && this.focusTask.cancel){
11017                     this.focusTask.cancel();
11018                 }
11019                 this.onDestroy();
11020                 Ext.ComponentMgr.unregister(this);
11021                 this.fireEvent('destroy', this);
11022                 this.purgeListeners();
11023                 this.destroying = false;
11024                 this.isDestroyed = true;
11025             }
11026         }
11027     },
11028
11029     deleteMembers : function(){
11030         var args = arguments;
11031         for(var i = 0, len = args.length; i < len; ++i){
11032             delete this[args[i]];
11033         }
11034     },
11035
11036     
11037     beforeDestroy : Ext.emptyFn,
11038
11039     
11040     onDestroy  : Ext.emptyFn,
11041
11042     
11043     getEl : function(){
11044         return this.el;
11045     },
11046
11047     
11048     getContentTarget : function(){
11049         return this.el;
11050     },
11051
11052     
11053     getId : function(){
11054         return this.id || (this.id = 'ext-comp-' + (++Ext.Component.AUTO_ID));
11055     },
11056
11057     
11058     getItemId : function(){
11059         return this.itemId || this.getId();
11060     },
11061
11062     
11063     focus : function(selectText, delay){
11064         if(delay){
11065             this.focusTask = new Ext.util.DelayedTask(this.focus, this, [selectText, false]);
11066             this.focusTask.delay(Ext.isNumber(delay) ? delay : 10);
11067             return this;
11068         }
11069         if(this.rendered && !this.isDestroyed){
11070             this.el.focus();
11071             if(selectText === true){
11072                 this.el.dom.select();
11073             }
11074         }
11075         return this;
11076     },
11077
11078     
11079     blur : function(){
11080         if(this.rendered){
11081             this.el.blur();
11082         }
11083         return this;
11084     },
11085
11086     
11087     disable : function( silent){
11088         if(this.rendered){
11089             this.onDisable();
11090         }
11091         this.disabled = true;
11092         if(silent !== true){
11093             this.fireEvent('disable', this);
11094         }
11095         return this;
11096     },
11097
11098     
11099     onDisable : function(){
11100         this.getActionEl().addClass(this.disabledClass);
11101         this.el.dom.disabled = true;
11102     },
11103
11104     
11105     enable : function(){
11106         if(this.rendered){
11107             this.onEnable();
11108         }
11109         this.disabled = false;
11110         this.fireEvent('enable', this);
11111         return this;
11112     },
11113
11114     
11115     onEnable : function(){
11116         this.getActionEl().removeClass(this.disabledClass);
11117         this.el.dom.disabled = false;
11118     },
11119
11120     
11121     setDisabled : function(disabled){
11122         return this[disabled ? 'disable' : 'enable']();
11123     },
11124
11125     
11126     show : function(){
11127         if(this.fireEvent('beforeshow', this) !== false){
11128             this.hidden = false;
11129             if(this.autoRender){
11130                 this.render(Ext.isBoolean(this.autoRender) ? Ext.getBody() : this.autoRender);
11131             }
11132             if(this.rendered){
11133                 this.onShow();
11134             }
11135             this.fireEvent('show', this);
11136         }
11137         return this;
11138     },
11139
11140     
11141     onShow : function(){
11142         this.getVisibilityEl().removeClass('x-hide-' + this.hideMode);
11143     },
11144
11145     
11146     hide : function(){
11147         if(this.fireEvent('beforehide', this) !== false){
11148             this.doHide();
11149             this.fireEvent('hide', this);
11150         }
11151         return this;
11152     },
11153
11154     
11155     doHide: function(){
11156         this.hidden = true;
11157         if(this.rendered){
11158             this.onHide();
11159         }
11160     },
11161
11162     
11163     onHide : function(){
11164         this.getVisibilityEl().addClass('x-hide-' + this.hideMode);
11165     },
11166
11167     
11168     getVisibilityEl : function(){
11169         return this.hideParent ? this.container : this.getActionEl();
11170     },
11171
11172     
11173     setVisible : function(visible){
11174         return this[visible ? 'show' : 'hide']();
11175     },
11176
11177     
11178     isVisible : function(){
11179         return this.rendered && this.getVisibilityEl().isVisible();
11180     },
11181
11182     
11183     cloneConfig : function(overrides){
11184         overrides = overrides || {};
11185         var id = overrides.id || Ext.id();
11186         var cfg = Ext.applyIf(overrides, this.initialConfig);
11187         cfg.id = id; 
11188         return new this.constructor(cfg);
11189     },
11190
11191     
11192     getXType : function(){
11193         return this.constructor.xtype;
11194     },
11195
11196     
11197     isXType : function(xtype, shallow){
11198         
11199         if (Ext.isFunction(xtype)){
11200             xtype = xtype.xtype; 
11201         }else if (Ext.isObject(xtype)){
11202             xtype = xtype.constructor.xtype; 
11203         }
11204
11205         return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;
11206     },
11207
11208     
11209     getXTypes : function(){
11210         var tc = this.constructor;
11211         if(!tc.xtypes){
11212             var c = [], sc = this;
11213             while(sc && sc.constructor.xtype){
11214                 c.unshift(sc.constructor.xtype);
11215                 sc = sc.constructor.superclass;
11216             }
11217             tc.xtypeChain = c;
11218             tc.xtypes = c.join('/');
11219         }
11220         return tc.xtypes;
11221     },
11222
11223     
11224     findParentBy : function(fn) {
11225         for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);
11226         return p || null;
11227     },
11228
11229     
11230     findParentByType : function(xtype, shallow){
11231         return this.findParentBy(function(c){
11232             return c.isXType(xtype, shallow);
11233         });
11234     },
11235     
11236     
11237     bubble : function(fn, scope, args){
11238         var p = this;
11239         while(p){
11240             if(fn.apply(scope || p, args || [p]) === false){
11241                 break;
11242             }
11243             p = p.ownerCt;
11244         }
11245         return this;
11246     },
11247
11248     
11249     getPositionEl : function(){
11250         return this.positionEl || this.el;
11251     },
11252
11253     
11254     purgeListeners : function(){
11255         Ext.Component.superclass.purgeListeners.call(this);
11256         if(this.mons){
11257             this.on('beforedestroy', this.clearMons, this, {single: true});
11258         }
11259     },
11260
11261     
11262     clearMons : function(){
11263         Ext.each(this.mons, function(m){
11264             m.item.un(m.ename, m.fn, m.scope);
11265         }, this);
11266         this.mons = [];
11267     },
11268
11269     
11270     createMons: function(){
11271         if(!this.mons){
11272             this.mons = [];
11273             this.on('beforedestroy', this.clearMons, this, {single: true});
11274         }
11275     },
11276
11277     
11278     mon : function(item, ename, fn, scope, opt){
11279         this.createMons();
11280         if(Ext.isObject(ename)){
11281             var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
11282
11283             var o = ename;
11284             for(var e in o){
11285                 if(propRe.test(e)){
11286                     continue;
11287                 }
11288                 if(Ext.isFunction(o[e])){
11289                     
11290                     this.mons.push({
11291                         item: item, ename: e, fn: o[e], scope: o.scope
11292                     });
11293                     item.on(e, o[e], o.scope, o);
11294                 }else{
11295                     
11296                     this.mons.push({
11297                         item: item, ename: e, fn: o[e], scope: o.scope
11298                     });
11299                     item.on(e, o[e]);
11300                 }
11301             }
11302             return;
11303         }
11304
11305         this.mons.push({
11306             item: item, ename: ename, fn: fn, scope: scope
11307         });
11308         item.on(ename, fn, scope, opt);
11309     },
11310
11311     
11312     mun : function(item, ename, fn, scope){
11313         var found, mon;
11314         this.createMons();
11315         for(var i = 0, len = this.mons.length; i < len; ++i){
11316             mon = this.mons[i];
11317             if(item === mon.item && ename == mon.ename && fn === mon.fn && scope === mon.scope){
11318                 this.mons.splice(i, 1);
11319                 item.un(ename, fn, scope);
11320                 found = true;
11321                 break;
11322             }
11323         }
11324         return found;
11325     },
11326
11327     
11328     nextSibling : function(){
11329         if(this.ownerCt){
11330             var index = this.ownerCt.items.indexOf(this);
11331             if(index != -1 && index+1 < this.ownerCt.items.getCount()){
11332                 return this.ownerCt.items.itemAt(index+1);
11333             }
11334         }
11335         return null;
11336     },
11337
11338     
11339     previousSibling : function(){
11340         if(this.ownerCt){
11341             var index = this.ownerCt.items.indexOf(this);
11342             if(index > 0){
11343                 return this.ownerCt.items.itemAt(index-1);
11344             }
11345         }
11346         return null;
11347     },
11348
11349     
11350     getBubbleTarget : function(){
11351         return this.ownerCt;
11352     }
11353 });
11354
11355 Ext.reg('component', Ext.Component);
11356
11357 Ext.Action = Ext.extend(Object, {
11358     
11359     
11360     
11361     
11362     
11363     
11364     
11365
11366     constructor : function(config){
11367         this.initialConfig = config;
11368         this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
11369         this.items = [];
11370     },
11371     
11372     
11373     isAction : true,
11374
11375     
11376     setText : function(text){
11377         this.initialConfig.text = text;
11378         this.callEach('setText', [text]);
11379     },
11380
11381     
11382     getText : function(){
11383         return this.initialConfig.text;
11384     },
11385
11386     
11387     setIconClass : function(cls){
11388         this.initialConfig.iconCls = cls;
11389         this.callEach('setIconClass', [cls]);
11390     },
11391
11392     
11393     getIconClass : function(){
11394         return this.initialConfig.iconCls;
11395     },
11396
11397     
11398     setDisabled : function(v){
11399         this.initialConfig.disabled = v;
11400         this.callEach('setDisabled', [v]);
11401     },
11402
11403     
11404     enable : function(){
11405         this.setDisabled(false);
11406     },
11407
11408     
11409     disable : function(){
11410         this.setDisabled(true);
11411     },
11412
11413     
11414     isDisabled : function(){
11415         return this.initialConfig.disabled;
11416     },
11417
11418     
11419     setHidden : function(v){
11420         this.initialConfig.hidden = v;
11421         this.callEach('setVisible', [!v]);
11422     },
11423
11424     
11425     show : function(){
11426         this.setHidden(false);
11427     },
11428
11429     
11430     hide : function(){
11431         this.setHidden(true);
11432     },
11433
11434     
11435     isHidden : function(){
11436         return this.initialConfig.hidden;
11437     },
11438
11439     
11440     setHandler : function(fn, scope){
11441         this.initialConfig.handler = fn;
11442         this.initialConfig.scope = scope;
11443         this.callEach('setHandler', [fn, scope]);
11444     },
11445
11446     
11447     each : function(fn, scope){
11448         Ext.each(this.items, fn, scope);
11449     },
11450
11451     
11452     callEach : function(fnName, args){
11453         var cs = this.items;
11454         for(var i = 0, len = cs.length; i < len; i++){
11455             cs[i][fnName].apply(cs[i], args);
11456         }
11457     },
11458
11459     
11460     addComponent : function(comp){
11461         this.items.push(comp);
11462         comp.on('destroy', this.removeComponent, this);
11463     },
11464
11465     
11466     removeComponent : function(comp){
11467         this.items.remove(comp);
11468     },
11469
11470     
11471     execute : function(){
11472         this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);
11473     }
11474 });
11475
11476 (function(){
11477 Ext.Layer = function(config, existingEl){
11478     config = config || {};
11479     var dh = Ext.DomHelper,
11480         cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
11481         
11482     if (existingEl) {
11483         this.dom = Ext.getDom(existingEl);
11484     }
11485     if(!this.dom){
11486         var o = config.dh || {tag: 'div', cls: 'x-layer'};
11487         this.dom = dh.append(pel, o);
11488     }
11489     if(config.cls){
11490         this.addClass(config.cls);
11491     }
11492     this.constrain = config.constrain !== false;
11493     this.setVisibilityMode(Ext.Element.VISIBILITY);
11494     if(config.id){
11495         this.id = this.dom.id = config.id;
11496     }else{
11497         this.id = Ext.id(this.dom);
11498     }
11499     this.zindex = config.zindex || this.getZIndex();
11500     this.position('absolute', this.zindex);
11501     if(config.shadow){
11502         this.shadowOffset = config.shadowOffset || 4;
11503         this.shadow = new Ext.Shadow({
11504             offset : this.shadowOffset,
11505             mode : config.shadow
11506         });
11507     }else{
11508         this.shadowOffset = 0;
11509     }
11510     this.useShim = config.shim !== false && Ext.useShims;
11511     this.useDisplay = config.useDisplay;
11512     this.hide();
11513 };
11514
11515 var supr = Ext.Element.prototype;
11516
11517
11518 var shims = [];
11519
11520 Ext.extend(Ext.Layer, Ext.Element, {
11521
11522     getZIndex : function(){
11523         return this.zindex || parseInt((this.getShim() || this).getStyle('z-index'), 10) || 11000;
11524     },
11525
11526     getShim : function(){
11527         if(!this.useShim){
11528             return null;
11529         }
11530         if(this.shim){
11531             return this.shim;
11532         }
11533         var shim = shims.shift();
11534         if(!shim){
11535             shim = this.createShim();
11536             shim.enableDisplayMode('block');
11537             shim.dom.style.display = 'none';
11538             shim.dom.style.visibility = 'visible';
11539         }
11540         var pn = this.dom.parentNode;
11541         if(shim.dom.parentNode != pn){
11542             pn.insertBefore(shim.dom, this.dom);
11543         }
11544         shim.setStyle('z-index', this.getZIndex()-2);
11545         this.shim = shim;
11546         return shim;
11547     },
11548
11549     hideShim : function(){
11550         if(this.shim){
11551             this.shim.setDisplayed(false);
11552             shims.push(this.shim);
11553             delete this.shim;
11554         }
11555     },
11556
11557     disableShadow : function(){
11558         if(this.shadow){
11559             this.shadowDisabled = true;
11560             this.shadow.hide();
11561             this.lastShadowOffset = this.shadowOffset;
11562             this.shadowOffset = 0;
11563         }
11564     },
11565
11566     enableShadow : function(show){
11567         if(this.shadow){
11568             this.shadowDisabled = false;
11569             this.shadowOffset = this.lastShadowOffset;
11570             delete this.lastShadowOffset;
11571             if(show){
11572                 this.sync(true);
11573             }
11574         }
11575     },
11576
11577     
11578     
11579     
11580     sync : function(doShow){
11581         var shadow = this.shadow;
11582         if(!this.updating && this.isVisible() && (shadow || this.useShim)){
11583             var shim = this.getShim(),
11584                 w = this.getWidth(),
11585                 h = this.getHeight(),
11586                 l = this.getLeft(true),
11587                 t = this.getTop(true);
11588
11589             if(shadow && !this.shadowDisabled){
11590                 if(doShow && !shadow.isVisible()){
11591                     shadow.show(this);
11592                 }else{
11593                     shadow.realign(l, t, w, h);
11594                 }
11595                 if(shim){
11596                     if(doShow){
11597                        shim.show();
11598                     }
11599                     
11600                     var shadowAdj = shadow.el.getXY(), shimStyle = shim.dom.style,
11601                         shadowSize = shadow.el.getSize();
11602                     shimStyle.left = (shadowAdj[0])+'px';
11603                     shimStyle.top = (shadowAdj[1])+'px';
11604                     shimStyle.width = (shadowSize.width)+'px';
11605                     shimStyle.height = (shadowSize.height)+'px';
11606                 }
11607             }else if(shim){
11608                 if(doShow){
11609                    shim.show();
11610                 }
11611                 shim.setSize(w, h);
11612                 shim.setLeftTop(l, t);
11613             }
11614         }
11615     },
11616
11617     
11618     destroy : function(){
11619         this.hideShim();
11620         if(this.shadow){
11621             this.shadow.hide();
11622         }
11623         this.removeAllListeners();
11624         Ext.removeNode(this.dom);
11625         delete this.dom;
11626     },
11627
11628     remove : function(){
11629         this.destroy();
11630     },
11631
11632     
11633     beginUpdate : function(){
11634         this.updating = true;
11635     },
11636
11637     
11638     endUpdate : function(){
11639         this.updating = false;
11640         this.sync(true);
11641     },
11642
11643     
11644     hideUnders : function(negOffset){
11645         if(this.shadow){
11646             this.shadow.hide();
11647         }
11648         this.hideShim();
11649     },
11650
11651     
11652     constrainXY : function(){
11653         if(this.constrain){
11654             var vw = Ext.lib.Dom.getViewWidth(),
11655                 vh = Ext.lib.Dom.getViewHeight();
11656             var s = Ext.getDoc().getScroll();
11657
11658             var xy = this.getXY();
11659             var x = xy[0], y = xy[1];
11660             var so = this.shadowOffset;
11661             var w = this.dom.offsetWidth+so, h = this.dom.offsetHeight+so;
11662             
11663             var moved = false;
11664             
11665             if((x + w) > vw+s.left){
11666                 x = vw - w - so;
11667                 moved = true;
11668             }
11669             if((y + h) > vh+s.top){
11670                 y = vh - h - so;
11671                 moved = true;
11672             }
11673             
11674             if(x < s.left){
11675                 x = s.left;
11676                 moved = true;
11677             }
11678             if(y < s.top){
11679                 y = s.top;
11680                 moved = true;
11681             }
11682             if(moved){
11683                 if(this.avoidY){
11684                     var ay = this.avoidY;
11685                     if(y <= ay && (y+h) >= ay){
11686                         y = ay-h-5;
11687                     }
11688                 }
11689                 xy = [x, y];
11690                 this.storeXY(xy);
11691                 supr.setXY.call(this, xy);
11692                 this.sync();
11693             }
11694         }
11695         return this;
11696     },
11697     
11698     getConstrainOffset : function(){
11699         return this.shadowOffset;    
11700     },
11701
11702     isVisible : function(){
11703         return this.visible;
11704     },
11705
11706     
11707     showAction : function(){
11708         this.visible = true; 
11709         if(this.useDisplay === true){
11710             this.setDisplayed('');
11711         }else if(this.lastXY){
11712             supr.setXY.call(this, this.lastXY);
11713         }else if(this.lastLT){
11714             supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
11715         }
11716     },
11717
11718     
11719     hideAction : function(){
11720         this.visible = false;
11721         if(this.useDisplay === true){
11722             this.setDisplayed(false);
11723         }else{
11724             this.setLeftTop(-10000,-10000);
11725         }
11726     },
11727
11728     
11729     setVisible : function(v, a, d, c, e){
11730         if(v){
11731             this.showAction();
11732         }
11733         if(a && v){
11734             var cb = function(){
11735                 this.sync(true);
11736                 if(c){
11737                     c();
11738                 }
11739             }.createDelegate(this);
11740             supr.setVisible.call(this, true, true, d, cb, e);
11741         }else{
11742             if(!v){
11743                 this.hideUnders(true);
11744             }
11745             var cb = c;
11746             if(a){
11747                 cb = function(){
11748                     this.hideAction();
11749                     if(c){
11750                         c();
11751                     }
11752                 }.createDelegate(this);
11753             }
11754             supr.setVisible.call(this, v, a, d, cb, e);
11755             if(v){
11756                 this.sync(true);
11757             }else if(!a){
11758                 this.hideAction();
11759             }
11760         }
11761         return this;
11762     },
11763
11764     storeXY : function(xy){
11765         delete this.lastLT;
11766         this.lastXY = xy;
11767     },
11768
11769     storeLeftTop : function(left, top){
11770         delete this.lastXY;
11771         this.lastLT = [left, top];
11772     },
11773
11774     
11775     beforeFx : function(){
11776         this.beforeAction();
11777         return Ext.Layer.superclass.beforeFx.apply(this, arguments);
11778     },
11779
11780     
11781     afterFx : function(){
11782         Ext.Layer.superclass.afterFx.apply(this, arguments);
11783         this.sync(this.isVisible());
11784     },
11785
11786     
11787     beforeAction : function(){
11788         if(!this.updating && this.shadow){
11789             this.shadow.hide();
11790         }
11791     },
11792
11793     
11794     setLeft : function(left){
11795         this.storeLeftTop(left, this.getTop(true));
11796         supr.setLeft.apply(this, arguments);
11797         this.sync();
11798         return this;
11799     },
11800
11801     setTop : function(top){
11802         this.storeLeftTop(this.getLeft(true), top);
11803         supr.setTop.apply(this, arguments);
11804         this.sync();
11805         return this;
11806     },
11807
11808     setLeftTop : function(left, top){
11809         this.storeLeftTop(left, top);
11810         supr.setLeftTop.apply(this, arguments);
11811         this.sync();
11812         return this;
11813     },
11814
11815     setXY : function(xy, a, d, c, e){
11816         this.fixDisplay();
11817         this.beforeAction();
11818         this.storeXY(xy);
11819         var cb = this.createCB(c);
11820         supr.setXY.call(this, xy, a, d, cb, e);
11821         if(!a){
11822             cb();
11823         }
11824         return this;
11825     },
11826
11827     
11828     createCB : function(c){
11829         var el = this;
11830         return function(){
11831             el.constrainXY();
11832             el.sync(true);
11833             if(c){
11834                 c();
11835             }
11836         };
11837     },
11838
11839     
11840     setX : function(x, a, d, c, e){
11841         this.setXY([x, this.getY()], a, d, c, e);
11842         return this;
11843     },
11844
11845     
11846     setY : function(y, a, d, c, e){
11847         this.setXY([this.getX(), y], a, d, c, e);
11848         return this;
11849     },
11850
11851     
11852     setSize : function(w, h, a, d, c, e){
11853         this.beforeAction();
11854         var cb = this.createCB(c);
11855         supr.setSize.call(this, w, h, a, d, cb, e);
11856         if(!a){
11857             cb();
11858         }
11859         return this;
11860     },
11861
11862     
11863     setWidth : function(w, a, d, c, e){
11864         this.beforeAction();
11865         var cb = this.createCB(c);
11866         supr.setWidth.call(this, w, a, d, cb, e);
11867         if(!a){
11868             cb();
11869         }
11870         return this;
11871     },
11872
11873     
11874     setHeight : function(h, a, d, c, e){
11875         this.beforeAction();
11876         var cb = this.createCB(c);
11877         supr.setHeight.call(this, h, a, d, cb, e);
11878         if(!a){
11879             cb();
11880         }
11881         return this;
11882     },
11883
11884     
11885     setBounds : function(x, y, w, h, a, d, c, e){
11886         this.beforeAction();
11887         var cb = this.createCB(c);
11888         if(!a){
11889             this.storeXY([x, y]);
11890             supr.setXY.call(this, [x, y]);
11891             supr.setSize.call(this, w, h, a, d, cb, e);
11892             cb();
11893         }else{
11894             supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
11895         }
11896         return this;
11897     },
11898
11899     
11900     setZIndex : function(zindex){
11901         this.zindex = zindex;
11902         this.setStyle('z-index', zindex + 2);
11903         if(this.shadow){
11904             this.shadow.setZIndex(zindex + 1);
11905         }
11906         if(this.shim){
11907             this.shim.setStyle('z-index', zindex);
11908         }
11909         return this;
11910     }
11911 });
11912 })();
11913
11914 Ext.Shadow = function(config) {
11915     Ext.apply(this, config);
11916     if (typeof this.mode != "string") {
11917         this.mode = this.defaultMode;
11918     }
11919     var o = this.offset,
11920         a = {
11921             h: 0
11922         },
11923         rad = Math.floor(this.offset / 2);
11924     switch (this.mode.toLowerCase()) {
11925         
11926         case "drop":
11927             a.w = 0;
11928             a.l = a.t = o;
11929             a.t -= 1;
11930             if (Ext.isIE) {
11931                 a.l -= this.offset + rad;
11932                 a.t -= this.offset + rad;
11933                 a.w -= rad;
11934                 a.h -= rad;
11935                 a.t += 1;
11936             }
11937         break;
11938         case "sides":
11939             a.w = (o * 2);
11940             a.l = -o;
11941             a.t = o - 1;
11942             if (Ext.isIE) {
11943                 a.l -= (this.offset - rad);
11944                 a.t -= this.offset + rad;
11945                 a.l += 1;
11946                 a.w -= (this.offset - rad) * 2;
11947                 a.w -= rad + 1;
11948                 a.h -= 1;
11949             }
11950         break;
11951         case "frame":
11952             a.w = a.h = (o * 2);
11953             a.l = a.t = -o;
11954             a.t += 1;
11955             a.h -= 2;
11956             if (Ext.isIE) {
11957                 a.l -= (this.offset - rad);
11958                 a.t -= (this.offset - rad);
11959                 a.l += 1;
11960                 a.w -= (this.offset + rad + 1);
11961                 a.h -= (this.offset + rad);
11962                 a.h += 1;
11963             }
11964         break;
11965     };
11966
11967     this.adjusts = a;
11968 };
11969
11970 Ext.Shadow.prototype = {
11971     
11972     
11973     offset: 4,
11974
11975     
11976     defaultMode: "drop",
11977
11978     
11979     show: function(target) {
11980         target = Ext.get(target);
11981         if (!this.el) {
11982             this.el = Ext.Shadow.Pool.pull();
11983             if (this.el.dom.nextSibling != target.dom) {
11984                 this.el.insertBefore(target);
11985             }
11986         }
11987         this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10) - 1);
11988         if (Ext.isIE) {
11989             this.el.dom.style.filter = "progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius=" + (this.offset) + ")";
11990         }
11991         this.realign(
11992         target.getLeft(true),
11993         target.getTop(true),
11994         target.getWidth(),
11995         target.getHeight()
11996         );
11997         this.el.dom.style.display = "block";
11998     },
11999
12000     
12001     isVisible: function() {
12002         return this.el ? true: false;
12003     },
12004
12005     
12006     realign: function(l, t, w, h) {
12007         if (!this.el) {
12008             return;
12009         }
12010         var a = this.adjusts,
12011             d = this.el.dom,
12012             s = d.style,
12013             iea = 0,
12014             sw = (w + a.w),
12015             sh = (h + a.h),
12016             sws = sw + "px",
12017             shs = sh + "px",
12018             cn,
12019             sww;
12020         s.left = (l + a.l) + "px";
12021         s.top = (t + a.t) + "px";
12022         if (s.width != sws || s.height != shs) {
12023             s.width = sws;
12024             s.height = shs;
12025             if (!Ext.isIE) {
12026                 cn = d.childNodes;
12027                 sww = Math.max(0, (sw - 12)) + "px";
12028                 cn[0].childNodes[1].style.width = sww;
12029                 cn[1].childNodes[1].style.width = sww;
12030                 cn[2].childNodes[1].style.width = sww;
12031                 cn[1].style.height = Math.max(0, (sh - 12)) + "px";
12032             }
12033         }
12034     },
12035
12036     
12037     hide: function() {
12038         if (this.el) {
12039             this.el.dom.style.display = "none";
12040             Ext.Shadow.Pool.push(this.el);
12041             delete this.el;
12042         }
12043     },
12044
12045     
12046     setZIndex: function(z) {
12047         this.zIndex = z;
12048         if (this.el) {
12049             this.el.setStyle("z-index", z);
12050         }
12051     }
12052 };
12053
12054
12055 Ext.Shadow.Pool = function() {
12056     var p = [],
12057         markup = Ext.isIE ?
12058             '<div class="x-ie-shadow"></div>':
12059             '<div class="x-shadow"><div class="xst"><div class="xstl"></div><div class="xstc"></div><div class="xstr"></div></div><div class="xsc"><div class="xsml"></div><div class="xsmc"></div><div class="xsmr"></div></div><div class="xsb"><div class="xsbl"></div><div class="xsbc"></div><div class="xsbr"></div></div></div>';
12060     return {
12061         pull: function() {
12062             var sh = p.shift();
12063             if (!sh) {
12064                 sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
12065                 sh.autoBoxAdjust = false;
12066             }
12067             return sh;
12068         },
12069
12070         push: function(sh) {
12071             p.push(sh);
12072         }
12073     };
12074 }();
12075 Ext.BoxComponent = Ext.extend(Ext.Component, {
12076
12077     
12078     
12079     
12080     
12081     
12082     
12083     
12084     
12085     
12086     
12087     
12088     
12089     
12090     
12091     
12092     
12093     
12094     
12095     
12096     
12097     
12098     
12099     
12100
12101     
12102
12103     
12104     initComponent : function(){
12105         Ext.BoxComponent.superclass.initComponent.call(this);
12106         this.addEvents(
12107             
12108             'resize',
12109             
12110             'move'
12111         );
12112     },
12113
12114     
12115     boxReady : false,
12116     
12117     deferHeight: false,
12118
12119     
12120     setSize : function(w, h){
12121
12122         
12123         if(typeof w == 'object'){
12124             h = w.height;
12125             w = w.width;
12126         }
12127         if (Ext.isDefined(w) && Ext.isDefined(this.boxMinWidth) && (w < this.boxMinWidth)) {
12128             w = this.boxMinWidth;
12129         }
12130         if (Ext.isDefined(h) && Ext.isDefined(this.boxMinHeight) && (h < this.boxMinHeight)) {
12131             h = this.boxMinHeight;
12132         }
12133         if (Ext.isDefined(w) && Ext.isDefined(this.boxMaxWidth) && (w > this.boxMaxWidth)) {
12134             w = this.boxMaxWidth;
12135         }
12136         if (Ext.isDefined(h) && Ext.isDefined(this.boxMaxHeight) && (h > this.boxMaxHeight)) {
12137             h = this.boxMaxHeight;
12138         }
12139         
12140         if(!this.boxReady){
12141             this.width  = w;
12142             this.height = h;
12143             return this;
12144         }
12145
12146         
12147         if(this.cacheSizes !== false && this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
12148             return this;
12149         }
12150         this.lastSize = {width: w, height: h};
12151         var adj = this.adjustSize(w, h),
12152             aw = adj.width,
12153             ah = adj.height,
12154             rz;
12155         if(aw !== undefined || ah !== undefined){ 
12156             rz = this.getResizeEl();
12157             if(!this.deferHeight && aw !== undefined && ah !== undefined){
12158                 rz.setSize(aw, ah);
12159             }else if(!this.deferHeight && ah !== undefined){
12160                 rz.setHeight(ah);
12161             }else if(aw !== undefined){
12162                 rz.setWidth(aw);
12163             }
12164             this.onResize(aw, ah, w, h);
12165             this.fireEvent('resize', this, aw, ah, w, h);
12166         }
12167         return this;
12168     },
12169
12170     
12171     setWidth : function(width){
12172         return this.setSize(width);
12173     },
12174
12175     
12176     setHeight : function(height){
12177         return this.setSize(undefined, height);
12178     },
12179
12180     
12181     getSize : function(){
12182         return this.getResizeEl().getSize();
12183     },
12184
12185     
12186     getWidth : function(){
12187         return this.getResizeEl().getWidth();
12188     },
12189
12190     
12191     getHeight : function(){
12192         return this.getResizeEl().getHeight();
12193     },
12194
12195     
12196     getOuterSize : function(){
12197         var el = this.getResizeEl();
12198         return {width: el.getWidth() + el.getMargins('lr'),
12199                 height: el.getHeight() + el.getMargins('tb')};
12200     },
12201
12202     
12203     getPosition : function(local){
12204         var el = this.getPositionEl();
12205         if(local === true){
12206             return [el.getLeft(true), el.getTop(true)];
12207         }
12208         return this.xy || el.getXY();
12209     },
12210
12211     
12212     getBox : function(local){
12213         var pos = this.getPosition(local);
12214         var s = this.getSize();
12215         s.x = pos[0];
12216         s.y = pos[1];
12217         return s;
12218     },
12219
12220     
12221     updateBox : function(box){
12222         this.setSize(box.width, box.height);
12223         this.setPagePosition(box.x, box.y);
12224         return this;
12225     },
12226
12227     
12228     getResizeEl : function(){
12229         return this.resizeEl || this.el;
12230     },
12231
12232     
12233     setAutoScroll : function(scroll){
12234         if(this.rendered){
12235             this.getContentTarget().setOverflow(scroll ? 'auto' : '');
12236         }
12237         this.autoScroll = scroll;
12238         return this;
12239     },
12240
12241     
12242     setPosition : function(x, y){
12243         if(x && typeof x[1] == 'number'){
12244             y = x[1];
12245             x = x[0];
12246         }
12247         this.x = x;
12248         this.y = y;
12249         if(!this.boxReady){
12250             return this;
12251         }
12252         var adj = this.adjustPosition(x, y);
12253         var ax = adj.x, ay = adj.y;
12254
12255         var el = this.getPositionEl();
12256         if(ax !== undefined || ay !== undefined){
12257             if(ax !== undefined && ay !== undefined){
12258                 el.setLeftTop(ax, ay);
12259             }else if(ax !== undefined){
12260                 el.setLeft(ax);
12261             }else if(ay !== undefined){
12262                 el.setTop(ay);
12263             }
12264             this.onPosition(ax, ay);
12265             this.fireEvent('move', this, ax, ay);
12266         }
12267         return this;
12268     },
12269
12270     
12271     setPagePosition : function(x, y){
12272         if(x && typeof x[1] == 'number'){
12273             y = x[1];
12274             x = x[0];
12275         }
12276         this.pageX = x;
12277         this.pageY = y;
12278         if(!this.boxReady){
12279             return;
12280         }
12281         if(x === undefined || y === undefined){ 
12282             return;
12283         }
12284         var p = this.getPositionEl().translatePoints(x, y);
12285         this.setPosition(p.left, p.top);
12286         return this;
12287     },
12288
12289     
12290     afterRender : function(){
12291         Ext.BoxComponent.superclass.afterRender.call(this);
12292         if(this.resizeEl){
12293             this.resizeEl = Ext.get(this.resizeEl);
12294         }
12295         if(this.positionEl){
12296             this.positionEl = Ext.get(this.positionEl);
12297         }
12298         this.boxReady = true;
12299         Ext.isDefined(this.autoScroll) && this.setAutoScroll(this.autoScroll);
12300         this.setSize(this.width, this.height);
12301         if(this.x || this.y){
12302             this.setPosition(this.x, this.y);
12303         }else if(this.pageX || this.pageY){
12304             this.setPagePosition(this.pageX, this.pageY);
12305         }
12306     },
12307
12308     
12309     syncSize : function(){
12310         delete this.lastSize;
12311         this.setSize(this.autoWidth ? undefined : this.getResizeEl().getWidth(), this.autoHeight ? undefined : this.getResizeEl().getHeight());
12312         return this;
12313     },
12314
12315     
12316     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
12317     },
12318
12319     
12320     onPosition : function(x, y){
12321
12322     },
12323
12324     
12325     adjustSize : function(w, h){
12326         if(this.autoWidth){
12327             w = 'auto';
12328         }
12329         if(this.autoHeight){
12330             h = 'auto';
12331         }
12332         return {width : w, height: h};
12333     },
12334
12335     
12336     adjustPosition : function(x, y){
12337         return {x : x, y: y};
12338     }
12339 });
12340 Ext.reg('box', Ext.BoxComponent);
12341
12342
12343
12344 Ext.Spacer = Ext.extend(Ext.BoxComponent, {
12345     autoEl:'div'
12346 });
12347 Ext.reg('spacer', Ext.Spacer);
12348 Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
12349
12350     
12351     this.el = Ext.get(dragElement, true);
12352     this.el.dom.unselectable = "on";
12353     
12354     this.resizingEl = Ext.get(resizingElement, true);
12355
12356     
12357     this.orientation = orientation || Ext.SplitBar.HORIZONTAL;
12358
12359     
12360     
12361     this.minSize = 0;
12362
12363     
12364     this.maxSize = 2000;
12365
12366     
12367     this.animate = false;
12368
12369     
12370     this.useShim = false;
12371
12372     
12373     this.shim = null;
12374
12375     if(!existingProxy){
12376         
12377         this.proxy = Ext.SplitBar.createProxy(this.orientation);
12378     }else{
12379         this.proxy = Ext.get(existingProxy).dom;
12380     }
12381     
12382     this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
12383
12384     
12385     this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
12386
12387     
12388     this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
12389
12390     
12391     this.dragSpecs = {};
12392
12393     
12394     this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
12395     this.adapter.init(this);
12396
12397     if(this.orientation == Ext.SplitBar.HORIZONTAL){
12398         
12399         this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);
12400         this.el.addClass("x-splitbar-h");
12401     }else{
12402         
12403         this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);
12404         this.el.addClass("x-splitbar-v");
12405     }
12406
12407     this.addEvents(
12408         
12409         "resize",
12410         
12411         "moved",
12412         
12413         "beforeresize",
12414
12415         "beforeapply"
12416     );
12417
12418     Ext.SplitBar.superclass.constructor.call(this);
12419 };
12420
12421 Ext.extend(Ext.SplitBar, Ext.util.Observable, {
12422     onStartProxyDrag : function(x, y){
12423         this.fireEvent("beforeresize", this);
12424         this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: "&#160;"}, true);
12425         this.overlay.unselectable();
12426         this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
12427         this.overlay.show();
12428         Ext.get(this.proxy).setDisplayed("block");
12429         var size = this.adapter.getElementSize(this);
12430         this.activeMinSize = this.getMinimumSize();
12431         this.activeMaxSize = this.getMaximumSize();
12432         var c1 = size - this.activeMinSize;
12433         var c2 = Math.max(this.activeMaxSize - size, 0);
12434         if(this.orientation == Ext.SplitBar.HORIZONTAL){
12435             this.dd.resetConstraints();
12436             this.dd.setXConstraint(
12437                 this.placement == Ext.SplitBar.LEFT ? c1 : c2,
12438                 this.placement == Ext.SplitBar.LEFT ? c2 : c1,
12439                 this.tickSize
12440             );
12441             this.dd.setYConstraint(0, 0);
12442         }else{
12443             this.dd.resetConstraints();
12444             this.dd.setXConstraint(0, 0);
12445             this.dd.setYConstraint(
12446                 this.placement == Ext.SplitBar.TOP ? c1 : c2,
12447                 this.placement == Ext.SplitBar.TOP ? c2 : c1,
12448                 this.tickSize
12449             );
12450          }
12451         this.dragSpecs.startSize = size;
12452         this.dragSpecs.startPoint = [x, y];
12453         Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
12454     },
12455
12456     
12457     onEndProxyDrag : function(e){
12458         Ext.get(this.proxy).setDisplayed(false);
12459         var endPoint = Ext.lib.Event.getXY(e);
12460         if(this.overlay){
12461             Ext.destroy(this.overlay);
12462             delete this.overlay;
12463         }
12464         var newSize;
12465         if(this.orientation == Ext.SplitBar.HORIZONTAL){
12466             newSize = this.dragSpecs.startSize +
12467                 (this.placement == Ext.SplitBar.LEFT ?
12468                     endPoint[0] - this.dragSpecs.startPoint[0] :
12469                     this.dragSpecs.startPoint[0] - endPoint[0]
12470                 );
12471         }else{
12472             newSize = this.dragSpecs.startSize +
12473                 (this.placement == Ext.SplitBar.TOP ?
12474                     endPoint[1] - this.dragSpecs.startPoint[1] :
12475                     this.dragSpecs.startPoint[1] - endPoint[1]
12476                 );
12477         }
12478         newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
12479         if(newSize != this.dragSpecs.startSize){
12480             if(this.fireEvent('beforeapply', this, newSize) !== false){
12481                 this.adapter.setElementSize(this, newSize);
12482                 this.fireEvent("moved", this, newSize);
12483                 this.fireEvent("resize", this, newSize);
12484             }
12485         }
12486     },
12487
12488     
12489     getAdapter : function(){
12490         return this.adapter;
12491     },
12492
12493     
12494     setAdapter : function(adapter){
12495         this.adapter = adapter;
12496         this.adapter.init(this);
12497     },
12498
12499     
12500     getMinimumSize : function(){
12501         return this.minSize;
12502     },
12503
12504     
12505     setMinimumSize : function(minSize){
12506         this.minSize = minSize;
12507     },
12508
12509     
12510     getMaximumSize : function(){
12511         return this.maxSize;
12512     },
12513
12514     
12515     setMaximumSize : function(maxSize){
12516         this.maxSize = maxSize;
12517     },
12518
12519     
12520     setCurrentSize : function(size){
12521         var oldAnimate = this.animate;
12522         this.animate = false;
12523         this.adapter.setElementSize(this, size);
12524         this.animate = oldAnimate;
12525     },
12526
12527     
12528     destroy : function(removeEl){
12529         Ext.destroy(this.shim, Ext.get(this.proxy));
12530         this.dd.unreg();
12531         if(removeEl){
12532             this.el.remove();
12533         }
12534         this.purgeListeners();
12535     }
12536 });
12537
12538
12539 Ext.SplitBar.createProxy = function(dir){
12540     var proxy = new Ext.Element(document.createElement("div"));
12541     document.body.appendChild(proxy.dom);
12542     proxy.unselectable();
12543     var cls = 'x-splitbar-proxy';
12544     proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));
12545     return proxy.dom;
12546 };
12547
12548
12549 Ext.SplitBar.BasicLayoutAdapter = function(){
12550 };
12551
12552 Ext.SplitBar.BasicLayoutAdapter.prototype = {
12553     
12554     init : function(s){
12555
12556     },
12557     
12558      getElementSize : function(s){
12559         if(s.orientation == Ext.SplitBar.HORIZONTAL){
12560             return s.resizingEl.getWidth();
12561         }else{
12562             return s.resizingEl.getHeight();
12563         }
12564     },
12565
12566     
12567     setElementSize : function(s, newSize, onComplete){
12568         if(s.orientation == Ext.SplitBar.HORIZONTAL){
12569             if(!s.animate){
12570                 s.resizingEl.setWidth(newSize);
12571                 if(onComplete){
12572                     onComplete(s, newSize);
12573                 }
12574             }else{
12575                 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
12576             }
12577         }else{
12578
12579             if(!s.animate){
12580                 s.resizingEl.setHeight(newSize);
12581                 if(onComplete){
12582                     onComplete(s, newSize);
12583                 }
12584             }else{
12585                 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
12586             }
12587         }
12588     }
12589 };
12590
12591
12592 Ext.SplitBar.AbsoluteLayoutAdapter = function(container){
12593     this.basic = new Ext.SplitBar.BasicLayoutAdapter();
12594     this.container = Ext.get(container);
12595 };
12596
12597 Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
12598     init : function(s){
12599         this.basic.init(s);
12600     },
12601
12602     getElementSize : function(s){
12603         return this.basic.getElementSize(s);
12604     },
12605
12606     setElementSize : function(s, newSize, onComplete){
12607         this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
12608     },
12609
12610     moveSplitter : function(s){
12611         var yes = Ext.SplitBar;
12612         switch(s.placement){
12613             case yes.LEFT:
12614                 s.el.setX(s.resizingEl.getRight());
12615                 break;
12616             case yes.RIGHT:
12617                 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
12618                 break;
12619             case yes.TOP:
12620                 s.el.setY(s.resizingEl.getBottom());
12621                 break;
12622             case yes.BOTTOM:
12623                 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
12624                 break;
12625         }
12626     }
12627 };
12628
12629
12630 Ext.SplitBar.VERTICAL = 1;
12631
12632
12633 Ext.SplitBar.HORIZONTAL = 2;
12634
12635
12636 Ext.SplitBar.LEFT = 1;
12637
12638
12639 Ext.SplitBar.RIGHT = 2;
12640
12641
12642 Ext.SplitBar.TOP = 3;
12643
12644
12645 Ext.SplitBar.BOTTOM = 4;
12646
12647 Ext.Container = Ext.extend(Ext.BoxComponent, {
12648     
12649     
12650     
12651     
12652     bufferResize: 50,
12653
12654     
12655     
12656     
12657
12658
12659     
12660     autoDestroy : true,
12661
12662     
12663     forceLayout: false,
12664
12665     
12666     
12667     defaultType : 'panel',
12668
12669     
12670     resizeEvent: 'resize',
12671
12672     
12673     bubbleEvents: ['add', 'remove'],
12674
12675     
12676     initComponent : function(){
12677         Ext.Container.superclass.initComponent.call(this);
12678
12679         this.addEvents(
12680             
12681             'afterlayout',
12682             
12683             'beforeadd',
12684             
12685             'beforeremove',
12686             
12687             'add',
12688             
12689             'remove'
12690         );
12691
12692         
12693         var items = this.items;
12694         if(items){
12695             delete this.items;
12696             this.add(items);
12697         }
12698     },
12699
12700     
12701     initItems : function(){
12702         if(!this.items){
12703             this.items = new Ext.util.MixedCollection(false, this.getComponentId);
12704             this.getLayout(); 
12705         }
12706     },
12707
12708     
12709     setLayout : function(layout){
12710         if(this.layout && this.layout != layout){
12711             this.layout.setContainer(null);
12712         }
12713         this.layout = layout;
12714         this.initItems();
12715         layout.setContainer(this);
12716     },
12717
12718     afterRender: function(){
12719         
12720         
12721         Ext.Container.superclass.afterRender.call(this);
12722         if(!this.layout){
12723             this.layout = 'auto';
12724         }
12725         if(Ext.isObject(this.layout) && !this.layout.layout){
12726             this.layoutConfig = this.layout;
12727             this.layout = this.layoutConfig.type;
12728         }
12729         if(Ext.isString(this.layout)){
12730             this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
12731         }
12732         this.setLayout(this.layout);
12733
12734         
12735         if(this.activeItem !== undefined && this.layout.setActiveItem){
12736             var item = this.activeItem;
12737             delete this.activeItem;
12738             this.layout.setActiveItem(item);
12739         }
12740
12741         
12742         if(!this.ownerCt){
12743             this.doLayout(false, true);
12744         }
12745
12746         
12747         
12748         if(this.monitorResize === true){
12749             Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
12750         }
12751     },
12752
12753     
12754     getLayoutTarget : function(){
12755         return this.el;
12756     },
12757
12758     
12759     getComponentId : function(comp){
12760         return comp.getItemId();
12761     },
12762
12763     
12764     add : function(comp){
12765         this.initItems();
12766         var args = arguments.length > 1;
12767         if(args || Ext.isArray(comp)){
12768             var result = [];
12769             Ext.each(args ? arguments : comp, function(c){
12770                 result.push(this.add(c));
12771             }, this);
12772             return result;
12773         }
12774         var c = this.lookupComponent(this.applyDefaults(comp));
12775         var index = this.items.length;
12776         if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
12777             this.items.add(c);
12778             
12779             c.onAdded(this, index);
12780             this.onAdd(c);
12781             this.fireEvent('add', this, c, index);
12782         }
12783         return c;
12784     },
12785
12786     onAdd : function(c){
12787         
12788     },
12789
12790     
12791     onAdded : function(container, pos) {
12792         
12793         this.ownerCt = container;
12794         this.initRef();
12795         
12796         this.cascade(function(c){
12797             c.initRef();
12798         });
12799         this.fireEvent('added', this, container, pos);
12800     },
12801
12802     
12803     insert : function(index, comp) {
12804         var args   = arguments,
12805             length = args.length,
12806             result = [],
12807             i, c;
12808         
12809         this.initItems();
12810         
12811         if (length > 2) {
12812             for (i = length - 1; i >= 1; --i) {
12813                 result.push(this.insert(index, args[i]));
12814             }
12815             return result;
12816         }
12817         
12818         c = this.lookupComponent(this.applyDefaults(comp));
12819         index = Math.min(index, this.items.length);
12820         
12821         if (this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false) {
12822             if (c.ownerCt == this) {
12823                 this.items.remove(c);
12824             }
12825             this.items.insert(index, c);
12826             c.onAdded(this, index);
12827             this.onAdd(c);
12828             this.fireEvent('add', this, c, index);
12829         }
12830         
12831         return c;
12832     },
12833
12834     
12835     applyDefaults : function(c){
12836         var d = this.defaults;
12837         if(d){
12838             if(Ext.isFunction(d)){
12839                 d = d.call(this, c);
12840             }
12841             if(Ext.isString(c)){
12842                 c = Ext.ComponentMgr.get(c);
12843                 Ext.apply(c, d);
12844             }else if(!c.events){
12845                 Ext.applyIf(c.isAction ? c.initialConfig : c, d);
12846             }else{
12847                 Ext.apply(c, d);
12848             }
12849         }
12850         return c;
12851     },
12852
12853     
12854     onBeforeAdd : function(item){
12855         if(item.ownerCt){
12856             item.ownerCt.remove(item, false);
12857         }
12858         if(this.hideBorders === true){
12859             item.border = (item.border === true);
12860         }
12861     },
12862
12863     
12864     remove : function(comp, autoDestroy){
12865         this.initItems();
12866         var c = this.getComponent(comp);
12867         if(c && this.fireEvent('beforeremove', this, c) !== false){
12868             this.doRemove(c, autoDestroy);
12869             this.fireEvent('remove', this, c);
12870         }
12871         return c;
12872     },
12873
12874     onRemove: function(c){
12875         
12876     },
12877
12878     
12879     doRemove: function(c, autoDestroy){
12880         var l = this.layout,
12881             hasLayout = l && this.rendered;
12882
12883         if(hasLayout){
12884             l.onRemove(c);
12885         }
12886         this.items.remove(c);
12887         c.onRemoved();
12888         this.onRemove(c);
12889         if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
12890             c.destroy();
12891         }
12892         if(hasLayout){
12893             l.afterRemove(c);
12894         }
12895     },
12896
12897     
12898     removeAll: function(autoDestroy){
12899         this.initItems();
12900         var item, rem = [], items = [];
12901         this.items.each(function(i){
12902             rem.push(i);
12903         });
12904         for (var i = 0, len = rem.length; i < len; ++i){
12905             item = rem[i];
12906             this.remove(item, autoDestroy);
12907             if(item.ownerCt !== this){
12908                 items.push(item);
12909             }
12910         }
12911         return items;
12912     },
12913
12914     
12915     getComponent : function(comp){
12916         if(Ext.isObject(comp)){
12917             comp = comp.getItemId();
12918         }
12919         return this.items.get(comp);
12920     },
12921
12922     
12923     lookupComponent : function(comp){
12924         if(Ext.isString(comp)){
12925             return Ext.ComponentMgr.get(comp);
12926         }else if(!comp.events){
12927             return this.createComponent(comp);
12928         }
12929         return comp;
12930     },
12931
12932     
12933     createComponent : function(config, defaultType){
12934         if (config.render) {
12935             return config;
12936         }
12937         
12938         
12939         var c = Ext.create(Ext.apply({
12940             ownerCt: this
12941         }, config), defaultType || this.defaultType);
12942         delete c.initialConfig.ownerCt;
12943         delete c.ownerCt;
12944         return c;
12945     },
12946
12947     
12948     canLayout : function() {
12949         var el = this.getVisibilityEl();
12950         return el && el.dom && !el.isStyle("display", "none");
12951     },
12952
12953     
12954
12955     doLayout : function(shallow, force){
12956         var rendered = this.rendered,
12957             forceLayout = force || this.forceLayout;
12958
12959         if(this.collapsed || !this.canLayout()){
12960             this.deferLayout = this.deferLayout || !shallow;
12961             if(!forceLayout){
12962                 return;
12963             }
12964             shallow = shallow && !this.deferLayout;
12965         } else {
12966             delete this.deferLayout;
12967         }
12968         if(rendered && this.layout){
12969             this.layout.layout();
12970         }
12971         if(shallow !== true && this.items){
12972             var cs = this.items.items;
12973             for(var i = 0, len = cs.length; i < len; i++){
12974                 var c = cs[i];
12975                 if(c.doLayout){
12976                     c.doLayout(false, forceLayout);
12977                 }
12978             }
12979         }
12980         if(rendered){
12981             this.onLayout(shallow, forceLayout);
12982         }
12983         
12984         this.hasLayout = true;
12985         delete this.forceLayout;
12986     },
12987
12988     onLayout : Ext.emptyFn,
12989
12990     
12991     shouldBufferLayout: function(){
12992         
12993         var hl = this.hasLayout;
12994         if(this.ownerCt){
12995             
12996             return hl ? !this.hasLayoutPending() : false;
12997         }
12998         
12999         return hl;
13000     },
13001
13002     
13003     hasLayoutPending: function(){
13004         
13005         var pending = false;
13006         this.ownerCt.bubble(function(c){
13007             if(c.layoutPending){
13008                 pending = true;
13009                 return false;
13010             }
13011         });
13012         return pending;
13013     },
13014
13015     onShow : function(){
13016         
13017         Ext.Container.superclass.onShow.call(this);
13018         
13019         if(Ext.isDefined(this.deferLayout)){
13020             delete this.deferLayout;
13021             this.doLayout(true);
13022         }
13023     },
13024
13025     
13026     getLayout : function(){
13027         if(!this.layout){
13028             var layout = new Ext.layout.AutoLayout(this.layoutConfig);
13029             this.setLayout(layout);
13030         }
13031         return this.layout;
13032     },
13033
13034     
13035     beforeDestroy : function(){
13036         var c;
13037         if(this.items){
13038             while(c = this.items.first()){
13039                 this.doRemove(c, true);
13040             }
13041         }
13042         if(this.monitorResize){
13043             Ext.EventManager.removeResizeListener(this.doLayout, this);
13044         }
13045         Ext.destroy(this.layout);
13046         Ext.Container.superclass.beforeDestroy.call(this);
13047     },
13048
13049     
13050     cascade : function(fn, scope, args){
13051         if(fn.apply(scope || this, args || [this]) !== false){
13052             if(this.items){
13053                 var cs = this.items.items;
13054                 for(var i = 0, len = cs.length; i < len; i++){
13055                     if(cs[i].cascade){
13056                         cs[i].cascade(fn, scope, args);
13057                     }else{
13058                         fn.apply(scope || cs[i], args || [cs[i]]);
13059                     }
13060                 }
13061             }
13062         }
13063         return this;
13064     },
13065
13066     
13067     findById : function(id){
13068         var m = null, 
13069             ct = this;
13070         this.cascade(function(c){
13071             if(ct != c && c.id === id){
13072                 m = c;
13073                 return false;
13074             }
13075         });
13076         return m;
13077     },
13078
13079     
13080     findByType : function(xtype, shallow){
13081         return this.findBy(function(c){
13082             return c.isXType(xtype, shallow);
13083         });
13084     },
13085
13086     
13087     find : function(prop, value){
13088         return this.findBy(function(c){
13089             return c[prop] === value;
13090         });
13091     },
13092
13093     
13094     findBy : function(fn, scope){
13095         var m = [], ct = this;
13096         this.cascade(function(c){
13097             if(ct != c && fn.call(scope || c, c, ct) === true){
13098                 m.push(c);
13099             }
13100         });
13101         return m;
13102     },
13103
13104     
13105     get : function(key){
13106         return this.getComponent(key);
13107     }
13108 });
13109
13110 Ext.Container.LAYOUTS = {};
13111 Ext.reg('container', Ext.Container);
13112
13113 Ext.layout.ContainerLayout = Ext.extend(Object, {
13114     
13115     
13116
13117     
13118
13119     
13120     monitorResize:false,
13121     
13122     activeItem : null,
13123
13124     constructor : function(config){
13125         this.id = Ext.id(null, 'ext-layout-');
13126         Ext.apply(this, config);
13127     },
13128
13129     type: 'container',
13130
13131     
13132     IEMeasureHack : function(target, viewFlag) {
13133         var tChildren = target.dom.childNodes, tLen = tChildren.length, c, d = [], e, i, ret;
13134         for (i = 0 ; i < tLen ; i++) {
13135             c = tChildren[i];
13136             e = Ext.get(c);
13137             if (e) {
13138                 d[i] = e.getStyle('display');
13139                 e.setStyle({display: 'none'});
13140             }
13141         }
13142         ret = target ? target.getViewSize(viewFlag) : {};
13143         for (i = 0 ; i < tLen ; i++) {
13144             c = tChildren[i];
13145             e = Ext.get(c);
13146             if (e) {
13147                 e.setStyle({display: d[i]});
13148             }
13149         }
13150         return ret;
13151     },
13152
13153     
13154     getLayoutTargetSize : Ext.EmptyFn,
13155
13156     
13157     layout : function(){
13158         var ct = this.container, target = ct.getLayoutTarget();
13159         if(!(this.hasLayout || Ext.isEmpty(this.targetCls))){
13160             target.addClass(this.targetCls);
13161         }
13162         this.onLayout(ct, target);
13163         ct.fireEvent('afterlayout', ct, this);
13164     },
13165
13166     
13167     onLayout : function(ct, target){
13168         this.renderAll(ct, target);
13169     },
13170
13171     
13172     isValidParent : function(c, target){
13173         return target && c.getPositionEl().dom.parentNode == (target.dom || target);
13174     },
13175
13176     
13177     renderAll : function(ct, target){
13178         var items = ct.items.items, i, c, len = items.length;
13179         for(i = 0; i < len; i++) {
13180             c = items[i];
13181             if(c && (!c.rendered || !this.isValidParent(c, target))){
13182                 this.renderItem(c, i, target);
13183             }
13184         }
13185     },
13186
13187     
13188     renderItem : function(c, position, target){
13189         if (c) {
13190             if (!c.rendered) {
13191                 c.render(target, position);
13192                 this.configureItem(c);
13193             } else if (!this.isValidParent(c, target)) {
13194                 if (Ext.isNumber(position)) {
13195                     position = target.dom.childNodes[position];
13196                 }
13197                 
13198                 target.dom.insertBefore(c.getPositionEl().dom, position || null);
13199                 c.container = target;
13200                 this.configureItem(c);
13201             }
13202         }
13203     },
13204
13205     
13206     
13207     getRenderedItems: function(ct){
13208         var t = ct.getLayoutTarget(), cti = ct.items.items, len = cti.length, i, c, items = [];
13209         for (i = 0; i < len; i++) {
13210             if((c = cti[i]).rendered && this.isValidParent(c, t) && c.shouldLayout !== false){
13211                 items.push(c);
13212             }
13213         };
13214         return items;
13215     },
13216
13217     
13218     configureItem: function(c){
13219         if (this.extraCls) {
13220             var t = c.getPositionEl ? c.getPositionEl() : c;
13221             t.addClass(this.extraCls);
13222         }
13223         
13224         
13225         if (c.doLayout && this.forceLayout) {
13226             c.doLayout();
13227         }
13228         if (this.renderHidden && c != this.activeItem) {
13229             c.hide();
13230         }
13231     },
13232
13233     onRemove: function(c){
13234         if(this.activeItem == c){
13235             delete this.activeItem;
13236         }
13237         if(c.rendered && this.extraCls){
13238             var t = c.getPositionEl ? c.getPositionEl() : c;
13239             t.removeClass(this.extraCls);
13240         }
13241     },
13242
13243     afterRemove: function(c){
13244         if(c.removeRestore){
13245             c.removeMode = 'container';
13246             delete c.removeRestore;
13247         }
13248     },
13249
13250     
13251     onResize: function(){
13252         var ct = this.container,
13253             b;
13254         if(ct.collapsed){
13255             return;
13256         }
13257         if(b = ct.bufferResize && ct.shouldBufferLayout()){
13258             if(!this.resizeTask){
13259                 this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);
13260                 this.resizeBuffer = Ext.isNumber(b) ? b : 50;
13261             }
13262             ct.layoutPending = true;
13263             this.resizeTask.delay(this.resizeBuffer);
13264         }else{
13265             this.runLayout();
13266         }
13267     },
13268
13269     runLayout: function(){
13270         var ct = this.container;
13271         this.layout();
13272         ct.onLayout();
13273         delete ct.layoutPending;
13274     },
13275
13276     
13277     setContainer : function(ct){
13278         
13279         if(this.monitorResize && ct != this.container){
13280             var old = this.container;
13281             if(old){
13282                 old.un(old.resizeEvent, this.onResize, this);
13283             }
13284             if(ct){
13285                 ct.on(ct.resizeEvent, this.onResize, this);
13286             }
13287         }
13288         this.container = ct;
13289     },
13290
13291     
13292     parseMargins : function(v){
13293         if (Ext.isNumber(v)) {
13294             v = v.toString();
13295         }
13296         var ms  = v.split(' '),
13297             len = ms.length;
13298             
13299         if (len == 1) {
13300             ms[1] = ms[2] = ms[3] = ms[0];
13301         } else if(len == 2) {
13302             ms[2] = ms[0];
13303             ms[3] = ms[1];
13304         } else if(len == 3) {
13305             ms[3] = ms[1];
13306         }
13307         
13308         return {
13309             top   :parseInt(ms[0], 10) || 0,
13310             right :parseInt(ms[1], 10) || 0,
13311             bottom:parseInt(ms[2], 10) || 0,
13312             left  :parseInt(ms[3], 10) || 0
13313         };
13314     },
13315
13316     
13317     fieldTpl: (function() {
13318         var t = new Ext.Template(
13319             '<div class="x-form-item {itemCls}" tabIndex="-1">',
13320                 '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>',
13321                 '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">',
13322                 '</div><div class="{clearCls}"></div>',
13323             '</div>'
13324         );
13325         t.disableFormats = true;
13326         return t.compile();
13327     })(),
13328
13329     
13330     destroy : function(){
13331         
13332         if(this.resizeTask && this.resizeTask.cancel){
13333             this.resizeTask.cancel();
13334         }
13335         if(this.container) {
13336             this.container.un(this.container.resizeEvent, this.onResize, this);
13337         }
13338         if(!Ext.isEmpty(this.targetCls)){
13339             var target = this.container.getLayoutTarget();
13340             if(target){
13341                 target.removeClass(this.targetCls);
13342             }
13343         }
13344     }
13345 });
13346 Ext.layout.AutoLayout = Ext.extend(Ext.layout.ContainerLayout, {
13347     type: 'auto',
13348
13349     monitorResize: true,
13350
13351     onLayout : function(ct, target){
13352         Ext.layout.AutoLayout.superclass.onLayout.call(this, ct, target);
13353         var cs = this.getRenderedItems(ct), len = cs.length, i, c;
13354         for(i = 0; i < len; i++){
13355             c = cs[i];
13356             if (c.doLayout){
13357                 
13358                 c.doLayout(true);
13359             }
13360         }
13361     }
13362 });
13363
13364 Ext.Container.LAYOUTS['auto'] = Ext.layout.AutoLayout;
13365
13366 Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {
13367     
13368     monitorResize:true,
13369
13370     type: 'fit',
13371
13372     getLayoutTargetSize : function() {
13373         var target = this.container.getLayoutTarget();
13374         if (!target) {
13375             return {};
13376         }
13377         
13378         return target.getStyleSize();
13379     },
13380
13381     
13382     onLayout : function(ct, target){
13383         Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
13384         if(!ct.collapsed){
13385             this.setItemSize(this.activeItem || ct.items.itemAt(0), this.getLayoutTargetSize());
13386         }
13387     },
13388
13389     
13390     setItemSize : function(item, size){
13391         if(item && size.height > 0){ 
13392             item.setSize(size);
13393         }
13394     }
13395 });
13396 Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;
13397 Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
13398     
13399     deferredRender : false,
13400
13401     
13402     layoutOnCardChange : false,
13403
13404     
13405     
13406     renderHidden : true,
13407
13408     type: 'card',
13409
13410     
13411     setActiveItem : function(item){
13412         var ai = this.activeItem,
13413             ct = this.container;
13414         item = ct.getComponent(item);
13415
13416         
13417         if(item && ai != item){
13418
13419             
13420             if(ai){
13421                 ai.hide();
13422                 if (ai.hidden !== true) {
13423                     return false;
13424                 }
13425                 ai.fireEvent('deactivate', ai);
13426             }
13427
13428             var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);
13429
13430             
13431             this.activeItem = item;
13432
13433             
13434             
13435             delete item.deferLayout;
13436
13437             
13438             item.show();
13439
13440             this.layout();
13441
13442             if(layout){
13443                 item.doLayout();
13444             }
13445             item.fireEvent('activate', item);
13446         }
13447     },
13448
13449     
13450     renderAll : function(ct, target){
13451         if(this.deferredRender){
13452             this.renderItem(this.activeItem, undefined, target);
13453         }else{
13454             Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
13455         }
13456     }
13457 });
13458 Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;
13459
13460 Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {
13461     
13462
13463     
13464     monitorResize : true,
13465
13466     type : 'anchor',
13467
13468     
13469     defaultAnchor : '100%',
13470
13471     parseAnchorRE : /^(r|right|b|bottom)$/i,
13472
13473
13474     getLayoutTargetSize : function() {
13475         var target = this.container.getLayoutTarget(), ret = {};
13476         if (target) {
13477             ret = target.getViewSize();
13478
13479             
13480             
13481             
13482             if (Ext.isIE && Ext.isStrict && ret.width == 0){
13483                 ret =  target.getStyleSize();
13484             }
13485             ret.width -= target.getPadding('lr');
13486             ret.height -= target.getPadding('tb');
13487         }
13488         return ret;
13489     },
13490
13491     
13492     onLayout : function(container, target) {
13493         Ext.layout.AnchorLayout.superclass.onLayout.call(this, container, target);
13494
13495         var size = this.getLayoutTargetSize(),
13496             containerWidth = size.width,
13497             containerHeight = size.height,
13498             overflow = target.getStyle('overflow'),
13499             components = this.getRenderedItems(container),
13500             len = components.length,
13501             boxes = [],
13502             box,
13503             anchorWidth,
13504             anchorHeight,
13505             component,
13506             anchorSpec,
13507             calcWidth,
13508             calcHeight,
13509             anchorsArray,
13510             totalHeight = 0,
13511             i,
13512             el;
13513
13514         if(containerWidth < 20 && containerHeight < 20){
13515             return;
13516         }
13517
13518         
13519         if(container.anchorSize) {
13520             if(typeof container.anchorSize == 'number') {
13521                 anchorWidth = container.anchorSize;
13522             } else {
13523                 anchorWidth = container.anchorSize.width;
13524                 anchorHeight = container.anchorSize.height;
13525             }
13526         } else {
13527             anchorWidth = container.initialConfig.width;
13528             anchorHeight = container.initialConfig.height;
13529         }
13530
13531         for(i = 0; i < len; i++) {
13532             component = components[i];
13533             el = component.getPositionEl();
13534
13535             
13536             if (!component.anchor && component.items && !Ext.isNumber(component.width) && !(Ext.isIE6 && Ext.isStrict)){
13537                 component.anchor = this.defaultAnchor;
13538             }
13539
13540             if(component.anchor) {
13541                 anchorSpec = component.anchorSpec;
13542                 
13543                 if(!anchorSpec){
13544                     anchorsArray = component.anchor.split(' ');
13545                     component.anchorSpec = anchorSpec = {
13546                         right: this.parseAnchor(anchorsArray[0], component.initialConfig.width, anchorWidth),
13547                         bottom: this.parseAnchor(anchorsArray[1], component.initialConfig.height, anchorHeight)
13548                     };
13549                 }
13550                 calcWidth = anchorSpec.right ? this.adjustWidthAnchor(anchorSpec.right(containerWidth) - el.getMargins('lr'), component) : undefined;
13551                 calcHeight = anchorSpec.bottom ? this.adjustHeightAnchor(anchorSpec.bottom(containerHeight) - el.getMargins('tb'), component) : undefined;
13552
13553                 if(calcWidth || calcHeight) {
13554                     boxes.push({
13555                         component: component,
13556                         width: calcWidth || undefined,
13557                         height: calcHeight || undefined
13558                     });
13559                 }
13560             }
13561         }
13562         for (i = 0, len = boxes.length; i < len; i++) {
13563             box = boxes[i];
13564             box.component.setSize(box.width, box.height);
13565         }
13566
13567         if (overflow && overflow != 'hidden' && !this.adjustmentPass) {
13568             var newTargetSize = this.getLayoutTargetSize();
13569             if (newTargetSize.width != size.width || newTargetSize.height != size.height){
13570                 this.adjustmentPass = true;
13571                 this.onLayout(container, target);
13572             }
13573         }
13574
13575         delete this.adjustmentPass;
13576     },
13577
13578     
13579     parseAnchor : function(a, start, cstart) {
13580         if (a && a != 'none') {
13581             var last;
13582             
13583             if (this.parseAnchorRE.test(a)) {
13584                 var diff = cstart - start;
13585                 return function(v){
13586                     if(v !== last){
13587                         last = v;
13588                         return v - diff;
13589                     }
13590                 };
13591             
13592             } else if(a.indexOf('%') != -1) {
13593                 var ratio = parseFloat(a.replace('%', ''))*.01;
13594                 return function(v){
13595                     if(v !== last){
13596                         last = v;
13597                         return Math.floor(v*ratio);
13598                     }
13599                 };
13600             
13601             } else {
13602                 a = parseInt(a, 10);
13603                 if (!isNaN(a)) {
13604                     return function(v) {
13605                         if (v !== last) {
13606                             last = v;
13607                             return v + a;
13608                         }
13609                     };
13610                 }
13611             }
13612         }
13613         return false;
13614     },
13615
13616     
13617     adjustWidthAnchor : function(value, comp){
13618         return value;
13619     },
13620
13621     
13622     adjustHeightAnchor : function(value, comp){
13623         return value;
13624     }
13625
13626     
13627 });
13628 Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
13629
13630 Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {
13631     
13632     monitorResize:true,
13633
13634     type: 'column',
13635
13636     extraCls: 'x-column',
13637
13638     scrollOffset : 0,
13639
13640     
13641
13642     targetCls: 'x-column-layout-ct',
13643
13644     isValidParent : function(c, target){
13645         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
13646     },
13647
13648     getLayoutTargetSize : function() {
13649         var target = this.container.getLayoutTarget(), ret;
13650         if (target) {
13651             ret = target.getViewSize();
13652
13653             
13654             
13655             
13656             if (Ext.isIE && Ext.isStrict && ret.width == 0){
13657                 ret =  target.getStyleSize();
13658             }
13659
13660             ret.width -= target.getPadding('lr');
13661             ret.height -= target.getPadding('tb');
13662         }
13663         return ret;
13664     },
13665
13666     renderAll : function(ct, target) {
13667         if(!this.innerCt){
13668             
13669             
13670             this.innerCt = target.createChild({cls:'x-column-inner'});
13671             this.innerCt.createChild({cls:'x-clear'});
13672         }
13673         Ext.layout.ColumnLayout.superclass.renderAll.call(this, ct, this.innerCt);
13674     },
13675
13676     
13677     onLayout : function(ct, target){
13678         var cs = ct.items.items,
13679             len = cs.length,
13680             c,
13681             i,
13682             m,
13683             margins = [];
13684
13685         this.renderAll(ct, target);
13686
13687         var size = this.getLayoutTargetSize();
13688
13689         if(size.width < 1 && size.height < 1){ 
13690             return;
13691         }
13692
13693         var w = size.width - this.scrollOffset,
13694             h = size.height,
13695             pw = w;
13696
13697         this.innerCt.setWidth(w);
13698
13699         
13700         
13701
13702         for(i = 0; i < len; i++){
13703             c = cs[i];
13704             m = c.getPositionEl().getMargins('lr');
13705             margins[i] = m;
13706             if(!c.columnWidth){
13707                 pw -= (c.getWidth() + m);
13708             }
13709         }
13710
13711         pw = pw < 0 ? 0 : pw;
13712
13713         for(i = 0; i < len; i++){
13714             c = cs[i];
13715             m = margins[i];
13716             if(c.columnWidth){
13717                 c.setSize(Math.floor(c.columnWidth * pw) - m);
13718             }
13719         }
13720
13721         
13722         
13723         if (Ext.isIE) {
13724             if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
13725                 var ts = this.getLayoutTargetSize();
13726                 if (ts.width != size.width){
13727                     this.adjustmentPass = true;
13728                     this.onLayout(ct, target);
13729                 }
13730             }
13731         }
13732         delete this.adjustmentPass;
13733     }
13734
13735     
13736 });
13737
13738 Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;
13739
13740 Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
13741     
13742     monitorResize:true,
13743     
13744     rendered : false,
13745
13746     type: 'border',
13747
13748     targetCls: 'x-border-layout-ct',
13749
13750     getLayoutTargetSize : function() {
13751         var target = this.container.getLayoutTarget();
13752         return target ? target.getViewSize() : {};
13753     },
13754
13755     
13756     onLayout : function(ct, target){
13757         var collapsed, i, c, pos, items = ct.items.items, len = items.length;
13758         if(!this.rendered){
13759             collapsed = [];
13760             for(i = 0; i < len; i++) {
13761                 c = items[i];
13762                 pos = c.region;
13763                 if(c.collapsed){
13764                     collapsed.push(c);
13765                 }
13766                 c.collapsed = false;
13767                 if(!c.rendered){
13768                     c.render(target, i);
13769                     c.getPositionEl().addClass('x-border-panel');
13770                 }
13771                 this[pos] = pos != 'center' && c.split ?
13772                     new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
13773                     new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
13774                 this[pos].render(target, c);
13775             }
13776             this.rendered = true;
13777         }
13778
13779         var size = this.getLayoutTargetSize();
13780         if(size.width < 20 || size.height < 20){ 
13781             if(collapsed){
13782                 this.restoreCollapsed = collapsed;
13783             }
13784             return;
13785         }else if(this.restoreCollapsed){
13786             collapsed = this.restoreCollapsed;
13787             delete this.restoreCollapsed;
13788         }
13789
13790         var w = size.width, h = size.height,
13791             centerW = w, centerH = h, centerY = 0, centerX = 0,
13792             n = this.north, s = this.south, west = this.west, e = this.east, c = this.center,
13793             b, m, totalWidth, totalHeight;
13794         if(!c && Ext.layout.BorderLayout.WARN !== false){
13795             throw 'No center region defined in BorderLayout ' + ct.id;
13796         }
13797
13798         if(n && n.isVisible()){
13799             b = n.getSize();
13800             m = n.getMargins();
13801             b.width = w - (m.left+m.right);
13802             b.x = m.left;
13803             b.y = m.top;
13804             centerY = b.height + b.y + m.bottom;
13805             centerH -= centerY;
13806             n.applyLayout(b);
13807         }
13808         if(s && s.isVisible()){
13809             b = s.getSize();
13810             m = s.getMargins();
13811             b.width = w - (m.left+m.right);
13812             b.x = m.left;
13813             totalHeight = (b.height + m.top + m.bottom);
13814             b.y = h - totalHeight + m.top;
13815             centerH -= totalHeight;
13816             s.applyLayout(b);
13817         }
13818         if(west && west.isVisible()){
13819             b = west.getSize();
13820             m = west.getMargins();
13821             b.height = centerH - (m.top+m.bottom);
13822             b.x = m.left;
13823             b.y = centerY + m.top;
13824             totalWidth = (b.width + m.left + m.right);
13825             centerX += totalWidth;
13826             centerW -= totalWidth;
13827             west.applyLayout(b);
13828         }
13829         if(e && e.isVisible()){
13830             b = e.getSize();
13831             m = e.getMargins();
13832             b.height = centerH - (m.top+m.bottom);
13833             totalWidth = (b.width + m.left + m.right);
13834             b.x = w - totalWidth + m.left;
13835             b.y = centerY + m.top;
13836             centerW -= totalWidth;
13837             e.applyLayout(b);
13838         }
13839         if(c){
13840             m = c.getMargins();
13841             var centerBox = {
13842                 x: centerX + m.left,
13843                 y: centerY + m.top,
13844                 width: centerW - (m.left+m.right),
13845                 height: centerH - (m.top+m.bottom)
13846             };
13847             c.applyLayout(centerBox);
13848         }
13849         if(collapsed){
13850             for(i = 0, len = collapsed.length; i < len; i++){
13851                 collapsed[i].collapse(false);
13852             }
13853         }
13854         if(Ext.isIE && Ext.isStrict){ 
13855             target.repaint();
13856         }
13857         
13858         if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
13859             var ts = this.getLayoutTargetSize();
13860             if (ts.width != size.width || ts.height != size.height){
13861                 this.adjustmentPass = true;
13862                 this.onLayout(ct, target);
13863             }
13864         }
13865         delete this.adjustmentPass;
13866     },
13867
13868     destroy: function() {
13869         var r = ['north', 'south', 'east', 'west'], i, region;
13870         for (i = 0; i < r.length; i++) {
13871             region = this[r[i]];
13872             if(region){
13873                 if(region.destroy){
13874                     region.destroy();
13875                 }else if (region.split){
13876                     region.split.destroy(true);
13877                 }
13878             }
13879         }
13880         Ext.layout.BorderLayout.superclass.destroy.call(this);
13881     }
13882
13883     
13884 });
13885
13886
13887 Ext.layout.BorderLayout.Region = function(layout, config, pos){
13888     Ext.apply(this, config);
13889     this.layout = layout;
13890     this.position = pos;
13891     this.state = {};
13892     if(typeof this.margins == 'string'){
13893         this.margins = this.layout.parseMargins(this.margins);
13894     }
13895     this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
13896     if(this.collapsible){
13897         if(typeof this.cmargins == 'string'){
13898             this.cmargins = this.layout.parseMargins(this.cmargins);
13899         }
13900         if(this.collapseMode == 'mini' && !this.cmargins){
13901             this.cmargins = {left:0,top:0,right:0,bottom:0};
13902         }else{
13903             this.cmargins = Ext.applyIf(this.cmargins || {},
13904                 pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
13905         }
13906     }
13907 };
13908
13909 Ext.layout.BorderLayout.Region.prototype = {
13910     
13911     
13912     
13913     
13914     
13915     
13916     collapsible : false,
13917     
13918     split:false,
13919     
13920     floatable: true,
13921     
13922     minWidth:50,
13923     
13924     minHeight:50,
13925
13926     
13927     defaultMargins : {left:0,top:0,right:0,bottom:0},
13928     
13929     defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
13930     
13931     defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
13932     floatingZIndex: 100,
13933
13934     
13935     isCollapsed : false,
13936
13937     
13938     
13939     
13940
13941     
13942     render : function(ct, p){
13943         this.panel = p;
13944         p.el.enableDisplayMode();
13945         this.targetEl = ct;
13946         this.el = p.el;
13947
13948         var gs = p.getState, ps = this.position;
13949         p.getState = function(){
13950             return Ext.apply(gs.call(p) || {}, this.state);
13951         }.createDelegate(this);
13952
13953         if(ps != 'center'){
13954             p.allowQueuedExpand = false;
13955             p.on({
13956                 beforecollapse: this.beforeCollapse,
13957                 collapse: this.onCollapse,
13958                 beforeexpand: this.beforeExpand,
13959                 expand: this.onExpand,
13960                 hide: this.onHide,
13961                 show: this.onShow,
13962                 scope: this
13963             });
13964             if(this.collapsible || this.floatable){
13965                 p.collapseEl = 'el';
13966                 p.slideAnchor = this.getSlideAnchor();
13967             }
13968             if(p.tools && p.tools.toggle){
13969                 p.tools.toggle.addClass('x-tool-collapse-'+ps);
13970                 p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
13971             }
13972         }
13973     },
13974
13975     
13976     getCollapsedEl : function(){
13977         if(!this.collapsedEl){
13978             if(!this.toolTemplate){
13979                 var tt = new Ext.Template(
13980                      '<div class="x-tool x-tool-{id}">&#160;</div>'
13981                 );
13982                 tt.disableFormats = true;
13983                 tt.compile();
13984                 Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
13985             }
13986             this.collapsedEl = this.targetEl.createChild({
13987                 cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
13988                 id: this.panel.id + '-xcollapsed'
13989             });
13990             this.collapsedEl.enableDisplayMode('block');
13991
13992             if(this.collapseMode == 'mini'){
13993                 this.collapsedEl.addClass('x-layout-cmini-'+this.position);
13994                 this.miniCollapsedEl = this.collapsedEl.createChild({
13995                     cls: "x-layout-mini x-layout-mini-"+this.position, html: "&#160;"
13996                 });
13997                 this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
13998                 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
13999                 this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
14000             }else {
14001                 if(this.collapsible !== false && !this.hideCollapseTool) {
14002                     var t = this.expandToolEl = this.toolTemplate.append(
14003                             this.collapsedEl.dom,
14004                             {id:'expand-'+this.position}, true);
14005                     t.addClassOnOver('x-tool-expand-'+this.position+'-over');
14006                     t.on('click', this.onExpandClick, this, {stopEvent:true});
14007                 }
14008                 if(this.floatable !== false || this.titleCollapse){
14009                    this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
14010                    this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this);
14011                 }
14012             }
14013         }
14014         return this.collapsedEl;
14015     },
14016
14017     
14018     onExpandClick : function(e){
14019         if(this.isSlid){
14020             this.panel.expand(false);
14021         }else{
14022             this.panel.expand();
14023         }
14024     },
14025
14026     
14027     onCollapseClick : function(e){
14028         this.panel.collapse();
14029     },
14030
14031     
14032     beforeCollapse : function(p, animate){
14033         this.lastAnim = animate;
14034         if(this.splitEl){
14035             this.splitEl.hide();
14036         }
14037         this.getCollapsedEl().show();
14038         var el = this.panel.getEl();
14039         this.originalZIndex = el.getStyle('z-index');
14040         el.setStyle('z-index', 100);
14041         this.isCollapsed = true;
14042         this.layout.layout();
14043     },
14044
14045     
14046     onCollapse : function(animate){
14047         this.panel.el.setStyle('z-index', 1);
14048         if(this.lastAnim === false || this.panel.animCollapse === false){
14049             this.getCollapsedEl().dom.style.visibility = 'visible';
14050         }else{
14051             this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
14052         }
14053         this.state.collapsed = true;
14054         this.panel.saveState();
14055     },
14056
14057     
14058     beforeExpand : function(animate){
14059         if(this.isSlid){
14060             this.afterSlideIn();
14061         }
14062         var c = this.getCollapsedEl();
14063         this.el.show();
14064         if(this.position == 'east' || this.position == 'west'){
14065             this.panel.setSize(undefined, c.getHeight());
14066         }else{
14067             this.panel.setSize(c.getWidth(), undefined);
14068         }
14069         c.hide();
14070         c.dom.style.visibility = 'hidden';
14071         this.panel.el.setStyle('z-index', this.floatingZIndex);
14072     },
14073
14074     
14075     onExpand : function(){
14076         this.isCollapsed = false;
14077         if(this.splitEl){
14078             this.splitEl.show();
14079         }
14080         this.layout.layout();
14081         this.panel.el.setStyle('z-index', this.originalZIndex);
14082         this.state.collapsed = false;
14083         this.panel.saveState();
14084     },
14085
14086     
14087     collapseClick : function(e){
14088         if(this.isSlid){
14089            e.stopPropagation();
14090            this.slideIn();
14091         }else{
14092            e.stopPropagation();
14093            this.slideOut();
14094         }
14095     },
14096
14097     
14098     onHide : function(){
14099         if(this.isCollapsed){
14100             this.getCollapsedEl().hide();
14101         }else if(this.splitEl){
14102             this.splitEl.hide();
14103         }
14104     },
14105
14106     
14107     onShow : function(){
14108         if(this.isCollapsed){
14109             this.getCollapsedEl().show();
14110         }else if(this.splitEl){
14111             this.splitEl.show();
14112         }
14113     },
14114
14115     
14116     isVisible : function(){
14117         return !this.panel.hidden;
14118     },
14119
14120     
14121     getMargins : function(){
14122         return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
14123     },
14124
14125     
14126     getSize : function(){
14127         return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
14128     },
14129
14130     
14131     setPanel : function(panel){
14132         this.panel = panel;
14133     },
14134
14135     
14136     getMinWidth: function(){
14137         return this.minWidth;
14138     },
14139
14140     
14141     getMinHeight: function(){
14142         return this.minHeight;
14143     },
14144
14145     
14146     applyLayoutCollapsed : function(box){
14147         var ce = this.getCollapsedEl();
14148         ce.setLeftTop(box.x, box.y);
14149         ce.setSize(box.width, box.height);
14150     },
14151
14152     
14153     applyLayout : function(box){
14154         if(this.isCollapsed){
14155             this.applyLayoutCollapsed(box);
14156         }else{
14157             this.panel.setPosition(box.x, box.y);
14158             this.panel.setSize(box.width, box.height);
14159         }
14160     },
14161
14162     
14163     beforeSlide: function(){
14164         this.panel.beforeEffect();
14165     },
14166
14167     
14168     afterSlide : function(){
14169         this.panel.afterEffect();
14170     },
14171
14172     
14173     initAutoHide : function(){
14174         if(this.autoHide !== false){
14175             if(!this.autoHideHd){
14176                 this.autoHideSlideTask = new Ext.util.DelayedTask(this.slideIn, this);
14177                 this.autoHideHd = {
14178                     "mouseout": function(e){
14179                         if(!e.within(this.el, true)){
14180                             this.autoHideSlideTask.delay(500);
14181                         }
14182                     },
14183                     "mouseover" : function(e){
14184                         this.autoHideSlideTask.cancel();
14185                     },
14186                     scope : this
14187                 };
14188             }
14189             this.el.on(this.autoHideHd);
14190             this.collapsedEl.on(this.autoHideHd);
14191         }
14192     },
14193
14194     
14195     clearAutoHide : function(){
14196         if(this.autoHide !== false){
14197             this.el.un("mouseout", this.autoHideHd.mouseout);
14198             this.el.un("mouseover", this.autoHideHd.mouseover);
14199             this.collapsedEl.un("mouseout", this.autoHideHd.mouseout);
14200             this.collapsedEl.un("mouseover", this.autoHideHd.mouseover);
14201         }
14202     },
14203
14204     
14205     clearMonitor : function(){
14206         Ext.getDoc().un("click", this.slideInIf, this);
14207     },
14208
14209     
14210     slideOut : function(){
14211         if(this.isSlid || this.el.hasActiveFx()){
14212             return;
14213         }
14214         this.isSlid = true;
14215         var ts = this.panel.tools, dh, pc;
14216         if(ts && ts.toggle){
14217             ts.toggle.hide();
14218         }
14219         this.el.show();
14220
14221         
14222         pc = this.panel.collapsed;
14223         this.panel.collapsed = false;
14224
14225         if(this.position == 'east' || this.position == 'west'){
14226             
14227             dh = this.panel.deferHeight;
14228             this.panel.deferHeight = false;
14229
14230             this.panel.setSize(undefined, this.collapsedEl.getHeight());
14231
14232             
14233             this.panel.deferHeight = dh;
14234         }else{
14235             this.panel.setSize(this.collapsedEl.getWidth(), undefined);
14236         }
14237
14238         
14239         this.panel.collapsed = pc;
14240
14241         this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
14242         this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
14243         this.el.setStyle("z-index", this.floatingZIndex+2);
14244         this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
14245         if(this.animFloat !== false){
14246             this.beforeSlide();
14247             this.el.slideIn(this.getSlideAnchor(), {
14248                 callback: function(){
14249                     this.afterSlide();
14250                     this.initAutoHide();
14251                     Ext.getDoc().on("click", this.slideInIf, this);
14252                 },
14253                 scope: this,
14254                 block: true
14255             });
14256         }else{
14257             this.initAutoHide();
14258              Ext.getDoc().on("click", this.slideInIf, this);
14259         }
14260     },
14261
14262     
14263     afterSlideIn : function(){
14264         this.clearAutoHide();
14265         this.isSlid = false;
14266         this.clearMonitor();
14267         this.el.setStyle("z-index", "");
14268         this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
14269         this.el.dom.style.left = this.restoreLT[0];
14270         this.el.dom.style.top = this.restoreLT[1];
14271
14272         var ts = this.panel.tools;
14273         if(ts && ts.toggle){
14274             ts.toggle.show();
14275         }
14276     },
14277
14278     
14279     slideIn : function(cb){
14280         if(!this.isSlid || this.el.hasActiveFx()){
14281             Ext.callback(cb);
14282             return;
14283         }
14284         this.isSlid = false;
14285         if(this.animFloat !== false){
14286             this.beforeSlide();
14287             this.el.slideOut(this.getSlideAnchor(), {
14288                 callback: function(){
14289                     this.el.hide();
14290                     this.afterSlide();
14291                     this.afterSlideIn();
14292                     Ext.callback(cb);
14293                 },
14294                 scope: this,
14295                 block: true
14296             });
14297         }else{
14298             this.el.hide();
14299             this.afterSlideIn();
14300         }
14301     },
14302
14303     
14304     slideInIf : function(e){
14305         if(!e.within(this.el)){
14306             this.slideIn();
14307         }
14308     },
14309
14310     
14311     anchors : {
14312         "west" : "left",
14313         "east" : "right",
14314         "north" : "top",
14315         "south" : "bottom"
14316     },
14317
14318     
14319     sanchors : {
14320         "west" : "l",
14321         "east" : "r",
14322         "north" : "t",
14323         "south" : "b"
14324     },
14325
14326     
14327     canchors : {
14328         "west" : "tl-tr",
14329         "east" : "tr-tl",
14330         "north" : "tl-bl",
14331         "south" : "bl-tl"
14332     },
14333
14334     
14335     getAnchor : function(){
14336         return this.anchors[this.position];
14337     },
14338
14339     
14340     getCollapseAnchor : function(){
14341         return this.canchors[this.position];
14342     },
14343
14344     
14345     getSlideAnchor : function(){
14346         return this.sanchors[this.position];
14347     },
14348
14349     
14350     getAlignAdj : function(){
14351         var cm = this.cmargins;
14352         switch(this.position){
14353             case "west":
14354                 return [0, 0];
14355             break;
14356             case "east":
14357                 return [0, 0];
14358             break;
14359             case "north":
14360                 return [0, 0];
14361             break;
14362             case "south":
14363                 return [0, 0];
14364             break;
14365         }
14366     },
14367
14368     
14369     getExpandAdj : function(){
14370         var c = this.collapsedEl, cm = this.cmargins;
14371         switch(this.position){
14372             case "west":
14373                 return [-(cm.right+c.getWidth()+cm.left), 0];
14374             break;
14375             case "east":
14376                 return [cm.right+c.getWidth()+cm.left, 0];
14377             break;
14378             case "north":
14379                 return [0, -(cm.top+cm.bottom+c.getHeight())];
14380             break;
14381             case "south":
14382                 return [0, cm.top+cm.bottom+c.getHeight()];
14383             break;
14384         }
14385     },
14386
14387     destroy : function(){
14388         if (this.autoHideSlideTask && this.autoHideSlideTask.cancel){
14389             this.autoHideSlideTask.cancel();
14390         }
14391         Ext.destroyMembers(this, 'miniCollapsedEl', 'collapsedEl', 'expandToolEl');
14392     }
14393 };
14394
14395
14396 Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
14397     Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
14398     
14399     this.applyLayout = this.applyFns[pos];
14400 };
14401
14402 Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
14403     
14404     
14405     splitTip : "Drag to resize.",
14406     
14407     collapsibleSplitTip : "Drag to resize. Double click to hide.",
14408     
14409     useSplitTips : false,
14410
14411     
14412     splitSettings : {
14413         north : {
14414             orientation: Ext.SplitBar.VERTICAL,
14415             placement: Ext.SplitBar.TOP,
14416             maxFn : 'getVMaxSize',
14417             minProp: 'minHeight',
14418             maxProp: 'maxHeight'
14419         },
14420         south : {
14421             orientation: Ext.SplitBar.VERTICAL,
14422             placement: Ext.SplitBar.BOTTOM,
14423             maxFn : 'getVMaxSize',
14424             minProp: 'minHeight',
14425             maxProp: 'maxHeight'
14426         },
14427         east : {
14428             orientation: Ext.SplitBar.HORIZONTAL,
14429             placement: Ext.SplitBar.RIGHT,
14430             maxFn : 'getHMaxSize',
14431             minProp: 'minWidth',
14432             maxProp: 'maxWidth'
14433         },
14434         west : {
14435             orientation: Ext.SplitBar.HORIZONTAL,
14436             placement: Ext.SplitBar.LEFT,
14437             maxFn : 'getHMaxSize',
14438             minProp: 'minWidth',
14439             maxProp: 'maxWidth'
14440         }
14441     },
14442
14443     
14444     applyFns : {
14445         west : function(box){
14446             if(this.isCollapsed){
14447                 return this.applyLayoutCollapsed(box);
14448             }
14449             var sd = this.splitEl.dom, s = sd.style;
14450             this.panel.setPosition(box.x, box.y);
14451             var sw = sd.offsetWidth;
14452             s.left = (box.x+box.width-sw)+'px';
14453             s.top = (box.y)+'px';
14454             s.height = Math.max(0, box.height)+'px';
14455             this.panel.setSize(box.width-sw, box.height);
14456         },
14457         east : function(box){
14458             if(this.isCollapsed){
14459                 return this.applyLayoutCollapsed(box);
14460             }
14461             var sd = this.splitEl.dom, s = sd.style;
14462             var sw = sd.offsetWidth;
14463             this.panel.setPosition(box.x+sw, box.y);
14464             s.left = (box.x)+'px';
14465             s.top = (box.y)+'px';
14466             s.height = Math.max(0, box.height)+'px';
14467             this.panel.setSize(box.width-sw, box.height);
14468         },
14469         north : function(box){
14470             if(this.isCollapsed){
14471                 return this.applyLayoutCollapsed(box);
14472             }
14473             var sd = this.splitEl.dom, s = sd.style;
14474             var sh = sd.offsetHeight;
14475             this.panel.setPosition(box.x, box.y);
14476             s.left = (box.x)+'px';
14477             s.top = (box.y+box.height-sh)+'px';
14478             s.width = Math.max(0, box.width)+'px';
14479             this.panel.setSize(box.width, box.height-sh);
14480         },
14481         south : function(box){
14482             if(this.isCollapsed){
14483                 return this.applyLayoutCollapsed(box);
14484             }
14485             var sd = this.splitEl.dom, s = sd.style;
14486             var sh = sd.offsetHeight;
14487             this.panel.setPosition(box.x, box.y+sh);
14488             s.left = (box.x)+'px';
14489             s.top = (box.y)+'px';
14490             s.width = Math.max(0, box.width)+'px';
14491             this.panel.setSize(box.width, box.height-sh);
14492         }
14493     },
14494
14495     
14496     render : function(ct, p){
14497         Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
14498
14499         var ps = this.position;
14500
14501         this.splitEl = ct.createChild({
14502             cls: "x-layout-split x-layout-split-"+ps, html: "&#160;",
14503             id: this.panel.id + '-xsplit'
14504         });
14505
14506         if(this.collapseMode == 'mini'){
14507             this.miniSplitEl = this.splitEl.createChild({
14508                 cls: "x-layout-mini x-layout-mini-"+ps, html: "&#160;"
14509             });
14510             this.miniSplitEl.addClassOnOver('x-layout-mini-over');
14511             this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
14512         }
14513
14514         var s = this.splitSettings[ps];
14515
14516         this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
14517         this.split.tickSize = this.tickSize;
14518         this.split.placement = s.placement;
14519         this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
14520         this.split.minSize = this.minSize || this[s.minProp];
14521         this.split.on("beforeapply", this.onSplitMove, this);
14522         this.split.useShim = this.useShim === true;
14523         this.maxSize = this.maxSize || this[s.maxProp];
14524
14525         if(p.hidden){
14526             this.splitEl.hide();
14527         }
14528
14529         if(this.useSplitTips){
14530             this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
14531         }
14532         if(this.collapsible){
14533             this.splitEl.on("dblclick", this.onCollapseClick,  this);
14534         }
14535     },
14536
14537     
14538     getSize : function(){
14539         if(this.isCollapsed){
14540             return this.collapsedEl.getSize();
14541         }
14542         var s = this.panel.getSize();
14543         if(this.position == 'north' || this.position == 'south'){
14544             s.height += this.splitEl.dom.offsetHeight;
14545         }else{
14546             s.width += this.splitEl.dom.offsetWidth;
14547         }
14548         return s;
14549     },
14550
14551     
14552     getHMaxSize : function(){
14553          var cmax = this.maxSize || 10000;
14554          var center = this.layout.center;
14555          return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
14556     },
14557
14558     
14559     getVMaxSize : function(){
14560         var cmax = this.maxSize || 10000;
14561         var center = this.layout.center;
14562         return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
14563     },
14564
14565     
14566     onSplitMove : function(split, newSize){
14567         var s = this.panel.getSize();
14568         this.lastSplitSize = newSize;
14569         if(this.position == 'north' || this.position == 'south'){
14570             this.panel.setSize(s.width, newSize);
14571             this.state.height = newSize;
14572         }else{
14573             this.panel.setSize(newSize, s.height);
14574             this.state.width = newSize;
14575         }
14576         this.layout.layout();
14577         this.panel.saveState();
14578         return false;
14579     },
14580
14581     
14582     getSplitBar : function(){
14583         return this.split;
14584     },
14585
14586     
14587     destroy : function() {
14588         Ext.destroy(this.miniSplitEl, this.split, this.splitEl);
14589         Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this);
14590     }
14591 });
14592
14593 Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;
14594
14595 Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
14596
14597     
14598     labelSeparator : ':',
14599
14600     
14601
14602     
14603     trackLabels: true,
14604
14605     type: 'form',
14606
14607     onRemove: function(c){
14608         Ext.layout.FormLayout.superclass.onRemove.call(this, c);
14609         if(this.trackLabels){
14610             c.un('show', this.onFieldShow, this);
14611             c.un('hide', this.onFieldHide, this);
14612         }
14613         
14614         var el = c.getPositionEl(),
14615             ct = c.getItemCt && c.getItemCt();
14616         if (c.rendered && ct) {
14617             if (el && el.dom) {
14618                 el.insertAfter(ct);
14619             }
14620             Ext.destroy(ct);
14621             Ext.destroyMembers(c, 'label', 'itemCt');
14622             if (c.customItemCt) {
14623                 Ext.destroyMembers(c, 'getItemCt', 'customItemCt');
14624             }
14625         }
14626     },
14627
14628     
14629     setContainer : function(ct){
14630         Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
14631         if(ct.labelAlign){
14632             ct.addClass('x-form-label-'+ct.labelAlign);
14633         }
14634
14635         if(ct.hideLabels){
14636             Ext.apply(this, {
14637                 labelStyle: 'display:none',
14638                 elementStyle: 'padding-left:0;',
14639                 labelAdjust: 0
14640             });
14641         }else{
14642             this.labelSeparator = Ext.isDefined(ct.labelSeparator) ? ct.labelSeparator : this.labelSeparator;
14643             ct.labelWidth = ct.labelWidth || 100;
14644             if(Ext.isNumber(ct.labelWidth)){
14645                 var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5;
14646                 Ext.apply(this, {
14647                     labelAdjust: ct.labelWidth + pad,
14648                     labelStyle: 'width:' + ct.labelWidth + 'px;',
14649                     elementStyle: 'padding-left:' + (ct.labelWidth + pad) + 'px'
14650                 });
14651             }
14652             if(ct.labelAlign == 'top'){
14653                 Ext.apply(this, {
14654                     labelStyle: 'width:auto;',
14655                     labelAdjust: 0,
14656                     elementStyle: 'padding-left:0;'
14657                 });
14658             }
14659         }
14660     },
14661
14662     
14663     isHide: function(c){
14664         return c.hideLabel || this.container.hideLabels;
14665     },
14666
14667     onFieldShow: function(c){
14668         c.getItemCt().removeClass('x-hide-' + c.hideMode);
14669
14670         
14671         if (c.isComposite) {
14672             c.doLayout();
14673         }
14674     },
14675
14676     onFieldHide: function(c){
14677         c.getItemCt().addClass('x-hide-' + c.hideMode);
14678     },
14679
14680     
14681     getLabelStyle: function(s){
14682         var ls = '', items = [this.labelStyle, s];
14683         for (var i = 0, len = items.length; i < len; ++i){
14684             if (items[i]){
14685                 ls += items[i];
14686                 if (ls.substr(-1, 1) != ';'){
14687                     ls += ';';
14688                 }
14689             }
14690         }
14691         return ls;
14692     },
14693
14694     
14695
14696     
14697     renderItem : function(c, position, target){
14698         if(c && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){
14699             var args = this.getTemplateArgs(c);
14700             if(Ext.isNumber(position)){
14701                 position = target.dom.childNodes[position] || null;
14702             }
14703             if(position){
14704                 c.itemCt = this.fieldTpl.insertBefore(position, args, true);
14705             }else{
14706                 c.itemCt = this.fieldTpl.append(target, args, true);
14707             }
14708             if(!c.getItemCt){
14709                 
14710                 
14711                 Ext.apply(c, {
14712                     getItemCt: function(){
14713                         return c.itemCt;
14714                     },
14715                     customItemCt: true
14716                 });
14717             }
14718             c.label = c.getItemCt().child('label.x-form-item-label');
14719             if(!c.rendered){
14720                 c.render('x-form-el-' + c.id);
14721             }else if(!this.isValidParent(c, target)){
14722                 Ext.fly('x-form-el-' + c.id).appendChild(c.getPositionEl());
14723             }
14724             if(this.trackLabels){
14725                 if(c.hidden){
14726                     this.onFieldHide(c);
14727                 }
14728                 c.on({
14729                     scope: this,
14730                     show: this.onFieldShow,
14731                     hide: this.onFieldHide
14732                 });
14733             }
14734             this.configureItem(c);
14735         }else {
14736             Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
14737         }
14738     },
14739
14740     
14741     getTemplateArgs: function(field) {
14742         var noLabelSep = !field.fieldLabel || field.hideLabel;
14743
14744         return {
14745             id            : field.id,
14746             label         : field.fieldLabel,
14747             itemCls       : (field.itemCls || this.container.itemCls || '') + (field.hideLabel ? ' x-hide-label' : ''),
14748             clearCls      : field.clearCls || 'x-form-clear-left',
14749             labelStyle    : this.getLabelStyle(field.labelStyle),
14750             elementStyle  : this.elementStyle || '',
14751             labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator)
14752         };
14753     },
14754
14755     
14756     adjustWidthAnchor: function(value, c){
14757         if(c.label && !this.isHide(c) && (this.container.labelAlign != 'top')){
14758             var adjust = Ext.isIE6 || (Ext.isIE && !Ext.isStrict);
14759             return value - this.labelAdjust + (adjust ? -3 : 0);
14760         }
14761         return value;
14762     },
14763
14764     adjustHeightAnchor : function(value, c){
14765         if(c.label && !this.isHide(c) && (this.container.labelAlign == 'top')){
14766             return value - c.label.getHeight();
14767         }
14768         return value;
14769     },
14770
14771     
14772     isValidParent : function(c, target){
14773         return target && this.container.getEl().contains(c.getPositionEl());
14774     }
14775
14776     
14777 });
14778
14779 Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
14780
14781 Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
14782     
14783     fill : true,
14784     
14785     autoWidth : true,
14786     
14787     titleCollapse : true,
14788     
14789     hideCollapseTool : false,
14790     
14791     collapseFirst : false,
14792     
14793     animate : false,
14794     
14795     sequence : false,
14796     
14797     activeOnTop : false,
14798
14799     type: 'accordion',
14800
14801     renderItem : function(c){
14802         if(this.animate === false){
14803             c.animCollapse = false;
14804         }
14805         c.collapsible = true;
14806         if(this.autoWidth){
14807             c.autoWidth = true;
14808         }
14809         if(this.titleCollapse){
14810             c.titleCollapse = true;
14811         }
14812         if(this.hideCollapseTool){
14813             c.hideCollapseTool = true;
14814         }
14815         if(this.collapseFirst !== undefined){
14816             c.collapseFirst = this.collapseFirst;
14817         }
14818         if(!this.activeItem && !c.collapsed){
14819             this.setActiveItem(c, true);
14820         }else if(this.activeItem && this.activeItem != c){
14821             c.collapsed = true;
14822         }
14823         Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);
14824         c.header.addClass('x-accordion-hd');
14825         c.on('beforeexpand', this.beforeExpand, this);
14826     },
14827
14828     onRemove: function(c){
14829         Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);
14830         if(c.rendered){
14831             c.header.removeClass('x-accordion-hd');
14832         }
14833         c.un('beforeexpand', this.beforeExpand, this);
14834     },
14835
14836     
14837     beforeExpand : function(p, anim){
14838         var ai = this.activeItem;
14839         if(ai){
14840             if(this.sequence){
14841                 delete this.activeItem;
14842                 if (!ai.collapsed){
14843                     ai.collapse({callback:function(){
14844                         p.expand(anim || true);
14845                     }, scope: this});
14846                     return false;
14847                 }
14848             }else{
14849                 ai.collapse(this.animate);
14850             }
14851         }
14852         this.setActive(p);
14853         if(this.activeOnTop){
14854             p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
14855         }
14856         
14857         this.layout();
14858     },
14859
14860     
14861     setItemSize : function(item, size){
14862         if(this.fill && item){
14863             var hh = 0, i, ct = this.getRenderedItems(this.container), len = ct.length, p;
14864             
14865             for (i = 0; i < len; i++) {
14866                 if((p = ct[i]) != item && !p.hidden){
14867                     hh += p.header.getHeight();
14868                 }
14869             };
14870             
14871             size.height -= hh;
14872             
14873             
14874             item.setSize(size);
14875         }
14876     },
14877
14878     
14879     setActiveItem : function(item){
14880         this.setActive(item, true);
14881     },
14882
14883     
14884     setActive : function(item, expand){
14885         var ai = this.activeItem;
14886         item = this.container.getComponent(item);
14887         if(ai != item){
14888             if(item.rendered && item.collapsed && expand){
14889                 item.expand();
14890             }else{
14891                 if(ai){
14892                    ai.fireEvent('deactivate', ai);
14893                 }
14894                 this.activeItem = item;
14895                 item.fireEvent('activate', item);
14896             }
14897         }
14898     }
14899 });
14900 Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;
14901
14902
14903 Ext.layout.Accordion = Ext.layout.AccordionLayout;
14904 Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
14905     
14906
14907     
14908     monitorResize:false,
14909
14910     type: 'table',
14911
14912     targetCls: 'x-table-layout-ct',
14913
14914     
14915     tableAttrs:null,
14916
14917     
14918     setContainer : function(ct){
14919         Ext.layout.TableLayout.superclass.setContainer.call(this, ct);
14920
14921         this.currentRow = 0;
14922         this.currentColumn = 0;
14923         this.cells = [];
14924     },
14925     
14926     
14927     onLayout : function(ct, target){
14928         var cs = ct.items.items, len = cs.length, c, i;
14929
14930         if(!this.table){
14931             target.addClass('x-table-layout-ct');
14932
14933             this.table = target.createChild(
14934                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
14935         }
14936         this.renderAll(ct, target);
14937     },
14938
14939     
14940     getRow : function(index){
14941         var row = this.table.tBodies[0].childNodes[index];
14942         if(!row){
14943             row = document.createElement('tr');
14944             this.table.tBodies[0].appendChild(row);
14945         }
14946         return row;
14947     },
14948
14949     
14950     getNextCell : function(c){
14951         var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
14952         var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];
14953         for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){
14954             if(!this.cells[rowIndex]){
14955                 this.cells[rowIndex] = [];
14956             }
14957             for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){
14958                 this.cells[rowIndex][colIndex] = true;
14959             }
14960         }
14961         var td = document.createElement('td');
14962         if(c.cellId){
14963             td.id = c.cellId;
14964         }
14965         var cls = 'x-table-layout-cell';
14966         if(c.cellCls){
14967             cls += ' ' + c.cellCls;
14968         }
14969         td.className = cls;
14970         if(c.colspan){
14971             td.colSpan = c.colspan;
14972         }
14973         if(c.rowspan){
14974             td.rowSpan = c.rowspan;
14975         }
14976         this.getRow(curRow).appendChild(td);
14977         return td;
14978     },
14979
14980     
14981     getNextNonSpan: function(colIndex, rowIndex){
14982         var cols = this.columns;
14983         while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {
14984             if(cols && colIndex >= cols){
14985                 rowIndex++;
14986                 colIndex = 0;
14987             }else{
14988                 colIndex++;
14989             }
14990         }
14991         return [colIndex, rowIndex];
14992     },
14993
14994     
14995     renderItem : function(c, position, target){
14996         
14997         if(!this.table){
14998             this.table = target.createChild(
14999                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
15000         }
15001         if(c && !c.rendered){
15002             c.render(this.getNextCell(c));
15003             this.configureItem(c);
15004         }else if(c && !this.isValidParent(c, target)){
15005             var container = this.getNextCell(c);
15006             container.insertBefore(c.getPositionEl().dom, null);
15007             c.container = Ext.get(container);
15008             this.configureItem(c);
15009         }
15010     },
15011
15012     
15013     isValidParent : function(c, target){
15014         return c.getPositionEl().up('table', 5).dom.parentNode === (target.dom || target);
15015     },
15016     
15017     destroy: function(){
15018         delete this.table;
15019         Ext.layout.TableLayout.superclass.destroy.call(this);
15020     }
15021
15022     
15023 });
15024
15025 Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;
15026 Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
15027
15028     extraCls: 'x-abs-layout-item',
15029
15030     type: 'absolute',
15031
15032     onLayout : function(ct, target){
15033         target.position();
15034         this.paddingLeft = target.getPadding('l');
15035         this.paddingTop = target.getPadding('t');
15036         Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
15037     },
15038
15039     
15040     adjustWidthAnchor : function(value, comp){
15041         return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;
15042     },
15043
15044     
15045     adjustHeightAnchor : function(value, comp){
15046         return  value ? value - comp.getPosition(true)[1] + this.paddingTop : value;
15047     }
15048     
15049 });
15050 Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
15051
15052 Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
15053     
15054     defaultMargins : {left:0,top:0,right:0,bottom:0},
15055     
15056     padding : '0',
15057     
15058     pack : 'start',
15059
15060     
15061     monitorResize : true,
15062     type: 'box',
15063     scrollOffset : 0,
15064     extraCls : 'x-box-item',
15065     targetCls : 'x-box-layout-ct',
15066     innerCls : 'x-box-inner',
15067
15068     constructor : function(config){
15069         Ext.layout.BoxLayout.superclass.constructor.call(this, config);
15070
15071         if (Ext.isString(this.defaultMargins)) {
15072             this.defaultMargins = this.parseMargins(this.defaultMargins);
15073         }
15074         
15075         var handler = this.overflowHandler;
15076         
15077         if (typeof handler == 'string') {
15078             handler = {
15079                 type: handler
15080             };
15081         }
15082         
15083         var handlerType = 'none';
15084         if (handler && handler.type != undefined) {
15085             handlerType = handler.type;
15086         }
15087         
15088         var constructor = Ext.layout.boxOverflow[handlerType];
15089         if (constructor[this.type]) {
15090             constructor = constructor[this.type];
15091         }
15092         
15093         this.overflowHandler = new constructor(this, handler);
15094     },
15095
15096     
15097     onLayout: function(container, target) {
15098         Ext.layout.BoxLayout.superclass.onLayout.call(this, container, target);
15099
15100         var tSize = this.getLayoutTargetSize(),
15101             items = this.getVisibleItems(container),
15102             calcs = this.calculateChildBoxes(items, tSize),
15103             boxes = calcs.boxes,
15104             meta  = calcs.meta;
15105         
15106         
15107         if (tSize.width > 0) {
15108             var handler = this.overflowHandler,
15109                 method  = meta.tooNarrow ? 'handleOverflow' : 'clearOverflow';
15110             
15111             var results = handler[method](calcs, tSize);
15112             
15113             if (results) {
15114                 if (results.targetSize) {
15115                     tSize = results.targetSize;
15116                 }
15117                 
15118                 if (results.recalculate) {
15119                     items = this.getVisibleItems(container);
15120                     calcs = this.calculateChildBoxes(items, tSize);
15121                     boxes = calcs.boxes;
15122                 }
15123             }
15124         }
15125         
15126         
15127         this.layoutTargetLastSize = tSize;
15128         
15129         
15130         this.childBoxCache = calcs;
15131         
15132         this.updateInnerCtSize(tSize, calcs);
15133         this.updateChildBoxes(boxes);
15134
15135         
15136         this.handleTargetOverflow(tSize, container, target);
15137     },
15138
15139     
15140     updateChildBoxes: function(boxes) {
15141         for (var i = 0, length = boxes.length; i < length; i++) {
15142             var box  = boxes[i],
15143                 comp = box.component;
15144             
15145             if (box.dirtySize) {
15146                 comp.setSize(box.width, box.height);
15147             }
15148             
15149             if (isNaN(box.left) || isNaN(box.top)) {
15150                 continue;
15151             }
15152             
15153             comp.setPosition(box.left, box.top);
15154         }
15155     },
15156
15157     
15158     updateInnerCtSize: function(tSize, calcs) {
15159         var align   = this.align,
15160             padding = this.padding,
15161             width   = tSize.width,
15162             height  = tSize.height;
15163         
15164         if (this.type == 'hbox') {
15165             var innerCtWidth  = width,
15166                 innerCtHeight = calcs.meta.maxHeight + padding.top + padding.bottom;
15167
15168             if (align == 'stretch') {
15169                 innerCtHeight = height;
15170             } else if (align == 'middle') {
15171                 innerCtHeight = Math.max(height, innerCtHeight);
15172             }
15173         } else {
15174             var innerCtHeight = height,
15175                 innerCtWidth  = calcs.meta.maxWidth + padding.left + padding.right;
15176
15177             if (align == 'stretch') {
15178                 innerCtWidth = width;
15179             } else if (align == 'center') {
15180                 innerCtWidth = Math.max(width, innerCtWidth);
15181             }
15182         }
15183
15184         this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
15185     },
15186
15187     
15188     handleTargetOverflow: function(previousTargetSize, container, target) {
15189         var overflow = target.getStyle('overflow');
15190
15191         if (overflow && overflow != 'hidden' &&!this.adjustmentPass) {
15192             var newTargetSize = this.getLayoutTargetSize();
15193             if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height){
15194                 this.adjustmentPass = true;
15195                 this.onLayout(container, target);
15196             }
15197         }
15198
15199         delete this.adjustmentPass;
15200     },
15201
15202     
15203     isValidParent : function(c, target) {
15204         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
15205     },
15206
15207     
15208     getVisibleItems: function(ct) {
15209         var ct  = ct || this.container,
15210             t   = ct.getLayoutTarget(),
15211             cti = ct.items.items,
15212             len = cti.length,
15213
15214             i, c, items = [];
15215
15216         for (i = 0; i < len; i++) {
15217             if((c = cti[i]).rendered && this.isValidParent(c, t) && c.hidden !== true  && c.collapsed !== true && c.shouldLayout !== false){
15218                 items.push(c);
15219             }
15220         }
15221
15222         return items;
15223     },
15224
15225     
15226     renderAll : function(ct, target) {
15227         if (!this.innerCt) {
15228             
15229             this.innerCt = target.createChild({cls:this.innerCls});
15230             this.padding = this.parseMargins(this.padding);
15231         }
15232         Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
15233     },
15234
15235     getLayoutTargetSize : function() {
15236         var target = this.container.getLayoutTarget(), ret;
15237         
15238         if (target) {
15239             ret = target.getViewSize();
15240
15241             
15242             
15243             
15244             if (Ext.isIE && Ext.isStrict && ret.width == 0){
15245                 ret =  target.getStyleSize();
15246             }
15247
15248             ret.width  -= target.getPadding('lr');
15249             ret.height -= target.getPadding('tb');
15250         }
15251         
15252         return ret;
15253     },
15254
15255     
15256     renderItem : function(c) {
15257         if(Ext.isString(c.margins)){
15258             c.margins = this.parseMargins(c.margins);
15259         }else if(!c.margins){
15260             c.margins = this.defaultMargins;
15261         }
15262         Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
15263     },
15264     
15265     
15266     destroy: function() {
15267         Ext.destroy(this.overflowHandler);
15268         
15269         Ext.layout.BoxLayout.superclass.destroy.apply(this, arguments);
15270     }
15271 });
15272
15273
15274
15275 Ext.ns('Ext.layout.boxOverflow');
15276
15277
15278
15279 Ext.layout.boxOverflow.None = Ext.extend(Object, {
15280     constructor: function(layout, config) {
15281         this.layout = layout;
15282         
15283         Ext.apply(this, config || {});
15284     },
15285     
15286     handleOverflow: Ext.emptyFn,
15287     
15288     clearOverflow: Ext.emptyFn
15289 });
15290
15291
15292 Ext.layout.boxOverflow.none = Ext.layout.boxOverflow.None;
15293
15294 Ext.layout.boxOverflow.Menu = Ext.extend(Ext.layout.boxOverflow.None, {
15295     
15296     afterCls: 'x-strip-right',
15297     
15298     
15299     noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
15300     
15301     constructor: function(layout) {
15302         Ext.layout.boxOverflow.Menu.superclass.constructor.apply(this, arguments);
15303         
15304         
15305         this.menuItems = [];
15306     },
15307     
15308     
15309     createInnerElements: function() {
15310         if (!this.afterCt) {
15311             this.afterCt  = this.layout.innerCt.insertSibling({cls: this.afterCls},  'before');
15312         }
15313     },
15314     
15315     
15316     clearOverflow: function(calculations, targetSize) {
15317         var newWidth = targetSize.width + (this.afterCt ? this.afterCt.getWidth() : 0),
15318             items    = this.menuItems;
15319         
15320         this.hideTrigger();
15321         
15322         for (var index = 0, length = items.length; index < length; index++) {
15323             items.pop().component.show();
15324         }
15325         
15326         return {
15327             targetSize: {
15328                 height: targetSize.height,
15329                 width : newWidth
15330             }
15331         };
15332     },
15333     
15334     
15335     showTrigger: function() {
15336         this.createMenu();
15337         this.menuTrigger.show();
15338     },
15339     
15340     
15341     hideTrigger: function() {
15342         if (this.menuTrigger != undefined) {
15343             this.menuTrigger.hide();
15344         }
15345     },
15346     
15347     
15348     beforeMenuShow: function(menu) {
15349         var items = this.menuItems,
15350             len   = items.length,
15351             item,
15352             prev;
15353
15354         var needsSep = function(group, item){
15355             return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
15356         };
15357         
15358         this.clearMenu();
15359         menu.removeAll();
15360         
15361         for (var i = 0; i < len; i++) {
15362             item = items[i].component;
15363             
15364             if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
15365                 menu.add('-');
15366             }
15367             
15368             this.addComponentToMenu(menu, item);
15369             prev = item;
15370         }
15371
15372         
15373         if (menu.items.length < 1) {
15374             menu.add(this.noItemsMenuText);
15375         }
15376     },
15377     
15378     
15379     createMenuConfig : function(component, hideOnClick){
15380         var config = Ext.apply({}, component.initialConfig),
15381             group  = component.toggleGroup;
15382
15383         Ext.copyTo(config, component, [
15384             'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
15385         ]);
15386
15387         Ext.apply(config, {
15388             text       : component.overflowText || component.text,
15389             hideOnClick: hideOnClick
15390         });
15391
15392         if (group || component.enableToggle) {
15393             Ext.apply(config, {
15394                 group  : group,
15395                 checked: component.pressed,
15396                 listeners: {
15397                     checkchange: function(item, checked){
15398                         component.toggle(checked);
15399                     }
15400                 }
15401             });
15402         }
15403
15404         delete config.ownerCt;
15405         delete config.xtype;
15406         delete config.id;
15407
15408         return config;
15409     },
15410
15411     
15412     addComponentToMenu : function(menu, component) {
15413         if (component instanceof Ext.Toolbar.Separator) {
15414             menu.add('-');
15415
15416         } else if (Ext.isFunction(component.isXType)) {
15417             if (component.isXType('splitbutton')) {
15418                 menu.add(this.createMenuConfig(component, true));
15419
15420             } else if (component.isXType('button')) {
15421                 menu.add(this.createMenuConfig(component, !component.menu));
15422
15423             } else if (component.isXType('buttongroup')) {
15424                 component.items.each(function(item){
15425                      this.addComponentToMenu(menu, item);
15426                 }, this);
15427             }
15428         }
15429     },
15430     
15431     
15432     clearMenu : function(){
15433         var menu = this.moreMenu;
15434         if (menu && menu.items) {
15435             menu.items.each(function(item){
15436                 delete item.menu;
15437             });
15438         }
15439     },
15440     
15441     
15442     createMenu: function() {
15443         if (!this.menuTrigger) {
15444             this.createInnerElements();
15445             
15446             
15447             this.menu = new Ext.menu.Menu({
15448                 ownerCt : this.layout.container,
15449                 listeners: {
15450                     scope: this,
15451                     beforeshow: this.beforeMenuShow
15452                 }
15453             });
15454
15455             
15456             this.menuTrigger = new Ext.Button({
15457                 iconCls : 'x-toolbar-more-icon',
15458                 cls     : 'x-toolbar-more',
15459                 menu    : this.menu,
15460                 renderTo: this.afterCt
15461             });
15462         }
15463     },
15464     
15465     
15466     destroy: function() {
15467         Ext.destroy(this.menu, this.menuTrigger);
15468     }
15469 });
15470
15471 Ext.layout.boxOverflow.menu = Ext.layout.boxOverflow.Menu;
15472
15473
15474
15475 Ext.layout.boxOverflow.HorizontalMenu = Ext.extend(Ext.layout.boxOverflow.Menu, {
15476     
15477     constructor: function() {
15478         Ext.layout.boxOverflow.HorizontalMenu.superclass.constructor.apply(this, arguments);
15479         
15480         var me = this,
15481             layout = me.layout,
15482             origFunction = layout.calculateChildBoxes;
15483         
15484         layout.calculateChildBoxes = function(visibleItems, targetSize) {
15485             var calcs = origFunction.apply(layout, arguments),
15486                 meta  = calcs.meta,
15487                 items = me.menuItems;
15488             
15489             
15490             
15491             var hiddenWidth = 0;
15492             for (var index = 0, length = items.length; index < length; index++) {
15493                 hiddenWidth += items[index].width;
15494             }
15495             
15496             meta.minimumWidth += hiddenWidth;
15497             meta.tooNarrow = meta.minimumWidth > targetSize.width;
15498             
15499             return calcs;
15500         };        
15501     },
15502     
15503     handleOverflow: function(calculations, targetSize) {
15504         this.showTrigger();
15505         
15506         var newWidth    = targetSize.width - this.afterCt.getWidth(),
15507             boxes       = calculations.boxes,
15508             usedWidth   = 0,
15509             recalculate = false;
15510         
15511         
15512         for (var index = 0, length = boxes.length; index < length; index++) {
15513             usedWidth += boxes[index].width;
15514         }
15515         
15516         var spareWidth = newWidth - usedWidth,
15517             showCount  = 0;
15518         
15519         
15520         for (var index = 0, length = this.menuItems.length; index < length; index++) {
15521             var hidden = this.menuItems[index],
15522                 comp   = hidden.component,
15523                 width  = hidden.width;
15524             
15525             if (width < spareWidth) {
15526                 comp.show();
15527                 
15528                 spareWidth -= width;
15529                 showCount ++;
15530                 recalculate = true;
15531             } else {
15532                 break;
15533             }
15534         }
15535                 
15536         if (recalculate) {
15537             this.menuItems = this.menuItems.slice(showCount);
15538         } else {
15539             for (var i = boxes.length - 1; i >= 0; i--) {
15540                 var item  = boxes[i].component,
15541                     right = boxes[i].left + boxes[i].width;
15542
15543                 if (right >= newWidth) {
15544                     this.menuItems.unshift({
15545                         component: item,
15546                         width    : boxes[i].width
15547                     });
15548
15549                     item.hide();
15550                 } else {
15551                     break;
15552                 }
15553             }
15554         }
15555         
15556         if (this.menuItems.length == 0) {
15557             this.hideTrigger();
15558         }
15559         
15560         return {
15561             targetSize: {
15562                 height: targetSize.height,
15563                 width : newWidth
15564             },
15565             recalculate: recalculate
15566         };
15567     }
15568 });
15569
15570 Ext.layout.boxOverflow.menu.hbox = Ext.layout.boxOverflow.HorizontalMenu;
15571 Ext.layout.boxOverflow.Scroller = Ext.extend(Ext.layout.boxOverflow.None, {
15572     
15573     animateScroll: true,
15574     
15575     
15576     scrollIncrement: 100,
15577     
15578     
15579     wheelIncrement: 3,
15580     
15581     
15582     scrollRepeatInterval: 400,
15583     
15584     
15585     scrollDuration: 0.4,
15586     
15587     
15588     beforeCls: 'x-strip-left',
15589     
15590     
15591     afterCls: 'x-strip-right',
15592     
15593     
15594     scrollerCls: 'x-strip-scroller',
15595     
15596     
15597     beforeScrollerCls: 'x-strip-scroller-left',
15598     
15599     
15600     afterScrollerCls: 'x-strip-scroller-right',
15601     
15602     
15603     createWheelListener: function() {
15604         this.layout.innerCt.on({
15605             scope     : this,
15606             mousewheel: function(e) {
15607                 e.stopEvent();
15608
15609                 this.scrollBy(e.getWheelDelta() * this.wheelIncrement * -1, false);
15610             }
15611         });
15612     },
15613     
15614     
15615     handleOverflow: function(calculations, targetSize) {
15616         this.createInnerElements();
15617         this.showScrollers();
15618     },
15619     
15620     
15621     clearOverflow: function() {
15622         this.hideScrollers();
15623     },
15624     
15625     
15626     showScrollers: function() {
15627         this.createScrollers();
15628         
15629         this.beforeScroller.show();
15630         this.afterScroller.show();
15631         
15632         this.updateScrollButtons();
15633     },
15634     
15635     
15636     hideScrollers: function() {
15637         if (this.beforeScroller != undefined) {
15638             this.beforeScroller.hide();
15639             this.afterScroller.hide();          
15640         }
15641     },
15642     
15643     
15644     createScrollers: function() {
15645         if (!this.beforeScroller && !this.afterScroller) {
15646             var before = this.beforeCt.createChild({
15647                 cls: String.format("{0} {1} ", this.scrollerCls, this.beforeScrollerCls)
15648             });
15649             
15650             var after = this.afterCt.createChild({
15651                 cls: String.format("{0} {1}", this.scrollerCls, this.afterScrollerCls)
15652             });
15653             
15654             before.addClassOnOver(this.beforeScrollerCls + '-hover');
15655             after.addClassOnOver(this.afterScrollerCls + '-hover');
15656             
15657             before.setVisibilityMode(Ext.Element.DISPLAY);
15658             after.setVisibilityMode(Ext.Element.DISPLAY);
15659             
15660             this.beforeRepeater = new Ext.util.ClickRepeater(before, {
15661                 interval: this.scrollRepeatInterval,
15662                 handler : this.scrollLeft,
15663                 scope   : this
15664             });
15665             
15666             this.afterRepeater = new Ext.util.ClickRepeater(after, {
15667                 interval: this.scrollRepeatInterval,
15668                 handler : this.scrollRight,
15669                 scope   : this
15670             });
15671             
15672             
15673             this.beforeScroller = before;
15674             
15675             
15676             this.afterScroller = after;
15677         }
15678     },
15679     
15680     
15681     destroy: function() {
15682         Ext.destroy(this.beforeScroller, this.afterScroller, this.beforeRepeater, this.afterRepeater, this.beforeCt, this.afterCt);
15683     },
15684     
15685     
15686     scrollBy: function(delta, animate) {
15687         this.scrollTo(this.getScrollPosition() + delta, animate);
15688     },
15689     
15690     
15691     getItem: function(item) {
15692         if (Ext.isString(item)) {
15693             item = Ext.getCmp(item);
15694         } else if (Ext.isNumber(item)) {
15695             item = this.items[item];
15696         }
15697         
15698         return item;
15699     },
15700     
15701     
15702     getScrollAnim: function() {
15703         return {
15704             duration: this.scrollDuration, 
15705             callback: this.updateScrollButtons, 
15706             scope   : this
15707         };
15708     },
15709     
15710     
15711     updateScrollButtons: function() {
15712         if (this.beforeScroller == undefined || this.afterScroller == undefined) {
15713             return;
15714         }
15715         
15716         var beforeMeth = this.atExtremeBefore()  ? 'addClass' : 'removeClass',
15717             afterMeth  = this.atExtremeAfter() ? 'addClass' : 'removeClass',
15718             beforeCls  = this.beforeScrollerCls + '-disabled',
15719             afterCls   = this.afterScrollerCls  + '-disabled';
15720         
15721         this.beforeScroller[beforeMeth](beforeCls);
15722         this.afterScroller[afterMeth](afterCls);
15723         this.scrolling = false;
15724     },
15725     
15726     
15727     atExtremeBefore: function() {
15728         return this.getScrollPosition() === 0;
15729     },
15730     
15731     
15732     scrollLeft: function(animate) {
15733         this.scrollBy(-this.scrollIncrement, animate);
15734     },
15735     
15736     
15737     scrollRight: function(animate) {
15738         this.scrollBy(this.scrollIncrement, animate);
15739     },
15740     
15741     
15742     scrollToItem: function(item, animate) {
15743         item = this.getItem(item);
15744         
15745         if (item != undefined) {
15746             var visibility = this.getItemVisibility(item);
15747             
15748             if (!visibility.fullyVisible) {
15749                 var box  = item.getBox(true, true),
15750                     newX = box.x;
15751                     
15752                 if (visibility.hiddenRight) {
15753                     newX -= (this.layout.innerCt.getWidth() - box.width);
15754                 }
15755                 
15756                 this.scrollTo(newX, animate);
15757             }
15758         }
15759     },
15760     
15761     
15762     getItemVisibility: function(item) {
15763         var box         = this.getItem(item).getBox(true, true),
15764             itemLeft    = box.x,
15765             itemRight   = box.x + box.width,
15766             scrollLeft  = this.getScrollPosition(),
15767             scrollRight = this.layout.innerCt.getWidth() + scrollLeft;
15768         
15769         return {
15770             hiddenLeft  : itemLeft < scrollLeft,
15771             hiddenRight : itemRight > scrollRight,
15772             fullyVisible: itemLeft > scrollLeft && itemRight < scrollRight
15773         };
15774     }
15775 });
15776
15777 Ext.layout.boxOverflow.scroller = Ext.layout.boxOverflow.Scroller;
15778
15779
15780 \r
15781 Ext.layout.boxOverflow.VerticalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, {
15782     scrollIncrement: 75,
15783     wheelIncrement : 2,
15784     
15785     handleOverflow: function(calculations, targetSize) {
15786         Ext.layout.boxOverflow.VerticalScroller.superclass.handleOverflow.apply(this, arguments);
15787         
15788         return {
15789             targetSize: {
15790                 height: targetSize.height - (this.beforeCt.getHeight() + this.afterCt.getHeight()),
15791                 width : targetSize.width
15792             }
15793         };
15794     },
15795     
15796     
15797     createInnerElements: function() {
15798         var target = this.layout.innerCt;
15799         
15800         
15801         
15802         if (!this.beforeCt) {
15803             this.beforeCt = target.insertSibling({cls: this.beforeCls}, 'before');
15804             this.afterCt  = target.insertSibling({cls: this.afterCls},  'after');
15805
15806             this.createWheelListener();
15807         }
15808     },
15809     
15810     
15811     scrollTo: function(position, animate) {
15812         var oldPosition = this.getScrollPosition(),
15813             newPosition = position.constrain(0, this.getMaxScrollBottom());
15814         
15815         if (newPosition != oldPosition && !this.scrolling) {
15816             if (animate == undefined) {
15817                 animate = this.animateScroll;
15818             }
15819             
15820             this.layout.innerCt.scrollTo('top', newPosition, animate ? this.getScrollAnim() : false);
15821             
15822             if (animate) {
15823                 this.scrolling = true;
15824             } else {
15825                 this.scrolling = false;
15826                 this.updateScrollButtons();
15827             }
15828         }
15829     },
15830     
15831     
15832     getScrollPosition: function(){
15833         return parseInt(this.layout.innerCt.dom.scrollTop, 10) || 0;
15834     },
15835     
15836     
15837     getMaxScrollBottom: function() {
15838         return this.layout.innerCt.dom.scrollHeight - this.layout.innerCt.getHeight();
15839     },
15840     
15841     
15842     atExtremeAfter: function() {
15843         return this.getScrollPosition() >= this.getMaxScrollBottom();
15844     }
15845 });
15846
15847 Ext.layout.boxOverflow.scroller.vbox = Ext.layout.boxOverflow.VerticalScroller;
15848
15849
15850
15851 Ext.layout.boxOverflow.HorizontalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, {
15852     handleOverflow: function(calculations, targetSize) {
15853         Ext.layout.boxOverflow.HorizontalScroller.superclass.handleOverflow.apply(this, arguments);
15854         
15855         return {
15856             targetSize: {
15857                 height: targetSize.height,
15858                 width : targetSize.width - (this.beforeCt.getWidth() + this.afterCt.getWidth())
15859             }
15860         };
15861     },
15862     
15863     
15864     createInnerElements: function() {
15865         var target = this.layout.innerCt;
15866         
15867         
15868         
15869         if (!this.beforeCt) {
15870             this.afterCt  = target.insertSibling({cls: this.afterCls},  'before');
15871             this.beforeCt = target.insertSibling({cls: this.beforeCls}, 'before');
15872             
15873             this.createWheelListener();
15874         }
15875     },
15876     
15877     
15878     scrollTo: function(position, animate) {
15879         var oldPosition = this.getScrollPosition(),
15880             newPosition = position.constrain(0, this.getMaxScrollRight());
15881         
15882         if (newPosition != oldPosition && !this.scrolling) {
15883             if (animate == undefined) {
15884                 animate = this.animateScroll;
15885             }
15886             
15887             this.layout.innerCt.scrollTo('left', newPosition, animate ? this.getScrollAnim() : false);
15888             
15889             if (animate) {
15890                 this.scrolling = true;
15891             } else {
15892                 this.scrolling = false;
15893                 this.updateScrollButtons();
15894             }
15895         }
15896     },
15897     
15898     
15899     getScrollPosition: function(){
15900         return parseInt(this.layout.innerCt.dom.scrollLeft, 10) || 0;
15901     },
15902     
15903     
15904     getMaxScrollRight: function() {
15905         return this.layout.innerCt.dom.scrollWidth - this.layout.innerCt.getWidth();
15906     },
15907     
15908     
15909     atExtremeAfter: function() {
15910         return this.getScrollPosition() >= this.getMaxScrollRight();
15911     }
15912 });
15913
15914 Ext.layout.boxOverflow.scroller.hbox = Ext.layout.boxOverflow.HorizontalScroller;
15915 Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
15916     
15917     align: 'top', 
15918
15919     type : 'hbox',
15920
15921     
15922     
15923
15924     
15925     calculateChildBoxes: function(visibleItems, targetSize) {
15926         var visibleCount = visibleItems.length,
15927
15928             padding      = this.padding,
15929             topOffset    = padding.top,
15930             leftOffset   = padding.left,
15931             paddingVert  = topOffset  + padding.bottom,
15932             paddingHoriz = leftOffset + padding.right,
15933
15934             width        = targetSize.width - this.scrollOffset,
15935             height       = targetSize.height,
15936             availHeight  = Math.max(0, height - paddingVert),
15937
15938             isStart      = this.pack == 'start',
15939             isCenter     = this.pack == 'center',
15940             isEnd        = this.pack == 'end',
15941
15942             nonFlexWidth = 0,
15943             maxHeight    = 0,
15944             totalFlex    = 0,
15945             desiredWidth = 0,
15946             minimumWidth = 0,
15947
15948             
15949             boxes        = [],
15950
15951             
15952             child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedWidth, 
15953             horizMargins, vertMargins, stretchHeight;
15954
15955         
15956         for (i = 0; i < visibleCount; i++) {
15957             child       = visibleItems[i];
15958             childHeight = child.height;
15959             childWidth  = child.width;
15960             canLayout   = !child.hasLayout && typeof child.doLayout == 'function';
15961
15962             
15963             if (typeof childWidth != 'number') {
15964
15965                 
15966                 if (child.flex && !childWidth) {
15967                     totalFlex += child.flex;
15968
15969                 
15970                 } else {
15971                     
15972                     
15973                     if (!childWidth && canLayout) {
15974                         child.doLayout();
15975                     }
15976
15977                     childSize   = child.getSize();
15978                     childWidth  = childSize.width;
15979                     childHeight = childSize.height;
15980                 }
15981             }
15982
15983             childMargins = child.margins;
15984             horizMargins = childMargins.left + childMargins.right;
15985
15986             nonFlexWidth += horizMargins + (childWidth || 0);
15987             desiredWidth += horizMargins + (child.flex ? child.minWidth || 0 : childWidth);
15988             minimumWidth += horizMargins + (child.minWidth || childWidth || 0);
15989
15990             
15991             if (typeof childHeight != 'number') {
15992                 if (canLayout) {
15993                     child.doLayout();
15994                 }
15995                 childHeight = child.getHeight();
15996             }
15997
15998             maxHeight = Math.max(maxHeight, childHeight + childMargins.top + childMargins.bottom);
15999
16000             
16001             boxes.push({
16002                 component: child,
16003                 height   : childHeight || undefined,
16004                 width    : childWidth  || undefined
16005             });
16006         }
16007                 
16008         var shortfall = desiredWidth - width,
16009             tooNarrow = minimumWidth > width;
16010             
16011         
16012         var availableWidth = Math.max(0, width - nonFlexWidth - paddingHoriz);
16013         
16014         if (tooNarrow) {
16015             for (i = 0; i < visibleCount; i++) {
16016                 boxes[i].width = visibleItems[i].minWidth || visibleItems[i].width || boxes[i].width;
16017             }
16018         } else {
16019             
16020             
16021             if (shortfall > 0) {
16022                 var minWidths = [];
16023                 
16024                 
16025                 for (var index = 0, length = visibleCount; index < length; index++) {
16026                     var item     = visibleItems[index],
16027                         minWidth = item.minWidth || 0;
16028
16029                     
16030                     
16031                     if (item.flex) {
16032                         boxes[index].width = minWidth;
16033                     } else {
16034                         minWidths.push({
16035                             minWidth : minWidth,
16036                             available: boxes[index].width - minWidth,
16037                             index    : index
16038                         });
16039                     }
16040                 }
16041                 
16042                 
16043                 minWidths.sort(function(a, b) {
16044                     return a.available > b.available ? 1 : -1;
16045                 });
16046                 
16047                 
16048                 for (var i = 0, length = minWidths.length; i < length; i++) {
16049                     var itemIndex = minWidths[i].index;
16050                     
16051                     if (itemIndex == undefined) {
16052                         continue;
16053                     }
16054                         
16055                     var item      = visibleItems[itemIndex],
16056                         box       = boxes[itemIndex],
16057                         oldWidth  = box.width,
16058                         minWidth  = item.minWidth,
16059                         newWidth  = Math.max(minWidth, oldWidth - Math.ceil(shortfall / (length - i))),
16060                         reduction = oldWidth - newWidth;
16061                     
16062                     boxes[itemIndex].width = newWidth;
16063                     shortfall -= reduction;                    
16064                 }
16065             } else {
16066                 
16067                 var remainingWidth = availableWidth,
16068                     remainingFlex  = totalFlex;
16069
16070                 
16071                 for (i = 0; i < visibleCount; i++) {
16072                     child = visibleItems[i];
16073                     calcs = boxes[i];
16074
16075                     childMargins = child.margins;
16076                     vertMargins  = childMargins.top + childMargins.bottom;
16077
16078                     if (isStart && child.flex && !child.width) {
16079                         flexedWidth     = Math.ceil((child.flex / remainingFlex) * remainingWidth);
16080                         remainingWidth -= flexedWidth;
16081                         remainingFlex  -= child.flex;
16082
16083                         calcs.width = flexedWidth;
16084                         calcs.dirtySize = true;
16085                     }
16086                 }
16087             }
16088         }
16089         
16090         if (isCenter) {
16091             leftOffset += availableWidth / 2;
16092         } else if (isEnd) {
16093             leftOffset += availableWidth;
16094         }
16095         
16096         
16097         for (i = 0; i < visibleCount; i++) {
16098             child = visibleItems[i];
16099             calcs = boxes[i];
16100             
16101             childMargins = child.margins;
16102             leftOffset  += childMargins.left;
16103             vertMargins  = childMargins.top + childMargins.bottom;
16104             
16105             calcs.left = leftOffset;
16106             calcs.top  = topOffset + childMargins.top;
16107
16108             switch (this.align) {
16109                 case 'stretch':
16110                     stretchHeight = availHeight - vertMargins;
16111                     calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
16112                     calcs.dirtySize = true;
16113                     break;
16114                 case 'stretchmax':
16115                     stretchHeight = maxHeight - vertMargins;
16116                     calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
16117                     calcs.dirtySize = true;
16118                     break;
16119                 case 'middle':
16120                     var diff = availHeight - calcs.height - vertMargins;
16121                     if (diff > 0) {
16122                         calcs.top = topOffset + vertMargins + (diff / 2);
16123                     }
16124             }
16125             
16126             leftOffset += calcs.width + childMargins.right;
16127         }
16128
16129         return {
16130             boxes: boxes,
16131             meta : {
16132                 maxHeight   : maxHeight,
16133                 nonFlexWidth: nonFlexWidth,
16134                 desiredWidth: desiredWidth,
16135                 minimumWidth: minimumWidth,
16136                 shortfall   : desiredWidth - width,
16137                 tooNarrow   : tooNarrow
16138             }
16139         };
16140     }
16141 });
16142
16143 Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
16144 Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
16145     
16146     align : 'left', 
16147     type: 'vbox',
16148
16149     
16150
16151     
16152
16153     
16154     calculateChildBoxes: function(visibleItems, targetSize) {
16155         var visibleCount = visibleItems.length,
16156
16157             padding      = this.padding,
16158             topOffset    = padding.top,
16159             leftOffset   = padding.left,
16160             paddingVert  = topOffset  + padding.bottom,
16161             paddingHoriz = leftOffset + padding.right,
16162
16163             width        = targetSize.width - this.scrollOffset,
16164             height       = targetSize.height,
16165             availWidth   = Math.max(0, width - paddingHoriz),
16166
16167             isStart      = this.pack == 'start',
16168             isCenter     = this.pack == 'center',
16169             isEnd        = this.pack == 'end',
16170
16171             nonFlexHeight= 0,
16172             maxWidth     = 0,
16173             totalFlex    = 0,
16174             desiredHeight= 0,
16175             minimumHeight= 0,
16176
16177             
16178             boxes        = [],
16179             
16180             
16181             child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedWidth, 
16182             horizMargins, vertMargins, stretchWidth;
16183
16184         
16185         for (i = 0; i < visibleCount; i++) {
16186             child = visibleItems[i];
16187             childHeight = child.height;
16188             childWidth  = child.width;
16189             canLayout   = !child.hasLayout && typeof child.doLayout == 'function';
16190
16191             
16192             if (typeof childHeight != 'number') {
16193
16194                 
16195                 if (child.flex && !childHeight) {
16196                     totalFlex += child.flex;
16197
16198                 
16199                 } else {
16200                     
16201                     
16202                     if (!childHeight && canLayout) {
16203                         child.doLayout();
16204                     }
16205
16206                     childSize = child.getSize();
16207                     childWidth = childSize.width;
16208                     childHeight = childSize.height;
16209                 }
16210             }
16211             
16212             childMargins = child.margins;
16213             vertMargins  = childMargins.top + childMargins.bottom;
16214
16215             nonFlexHeight += vertMargins + (childHeight || 0);
16216             desiredHeight += vertMargins + (child.flex ? child.minHeight || 0 : childHeight);
16217             minimumHeight += vertMargins + (child.minHeight || childHeight || 0);
16218
16219             
16220             if (typeof childWidth != 'number') {
16221                 if (canLayout) {
16222                     child.doLayout();
16223                 }
16224                 childWidth = child.getWidth();
16225             }
16226
16227             maxWidth = Math.max(maxWidth, childWidth + childMargins.left + childMargins.right);
16228
16229             
16230             boxes.push({
16231                 component: child,
16232                 height   : childHeight || undefined,
16233                 width    : childWidth || undefined
16234             });
16235         }
16236                 
16237         var shortfall = desiredHeight - height,
16238             tooNarrow = minimumHeight > height;
16239
16240         
16241         var availableHeight = Math.max(0, (height - nonFlexHeight - paddingVert));
16242         
16243         if (tooNarrow) {
16244             for (i = 0, length = visibleCount; i < length; i++) {
16245                 boxes[i].height = visibleItems[i].minHeight || visibleItems[i].height || boxes[i].height;
16246             }
16247         } else {
16248             
16249             
16250             if (shortfall > 0) {
16251                 var minHeights = [];
16252
16253                 
16254                 for (var index = 0, length = visibleCount; index < length; index++) {
16255                     var item      = visibleItems[index],
16256                         minHeight = item.minHeight || 0;
16257
16258                     
16259                     
16260                     if (item.flex) {
16261                         boxes[index].height = minHeight;
16262                     } else {
16263                         minHeights.push({
16264                             minHeight: minHeight, 
16265                             available: boxes[index].height - minHeight,
16266                             index    : index
16267                         });
16268                     }
16269                 }
16270
16271                 
16272                 minHeights.sort(function(a, b) {
16273                     return a.available > b.available ? 1 : -1;
16274                 });
16275
16276                 
16277                 for (var i = 0, length = minHeights.length; i < length; i++) {
16278                     var itemIndex = minHeights[i].index;
16279
16280                     if (itemIndex == undefined) {
16281                         continue;
16282                     }
16283
16284                     var item      = visibleItems[itemIndex],
16285                         box       = boxes[itemIndex],
16286                         oldHeight  = box.height,
16287                         minHeight  = item.minHeight,
16288                         newHeight  = Math.max(minHeight, oldHeight - Math.ceil(shortfall / (length - i))),
16289                         reduction = oldHeight - newHeight;
16290
16291                     boxes[itemIndex].height = newHeight;
16292                     shortfall -= reduction;
16293                 }
16294             } else {
16295                 
16296                 var remainingHeight = availableHeight,
16297                     remainingFlex   = totalFlex;
16298                 
16299                 
16300                 for (i = 0; i < visibleCount; i++) {
16301                     child = visibleItems[i];
16302                     calcs = boxes[i];
16303
16304                     childMargins = child.margins;
16305                     horizMargins = childMargins.left + childMargins.right;
16306
16307                     if (isStart && child.flex && !child.height) {
16308                         flexedHeight     = Math.ceil((child.flex / remainingFlex) * remainingHeight);
16309                         remainingHeight -= flexedHeight;
16310                         remainingFlex   -= child.flex;
16311
16312                         calcs.height = flexedHeight;
16313                         calcs.dirtySize = true;
16314                     }
16315                 }
16316             }
16317         }
16318
16319         if (isCenter) {
16320             topOffset += availableHeight / 2;
16321         } else if (isEnd) {
16322             topOffset += availableHeight;
16323         }
16324
16325         
16326         for (i = 0; i < visibleCount; i++) {
16327             child = visibleItems[i];
16328             calcs = boxes[i];
16329
16330             childMargins = child.margins;
16331             topOffset   += childMargins.top;
16332             horizMargins = childMargins.left + childMargins.right;
16333             
16334
16335             calcs.left = leftOffset + childMargins.left;
16336             calcs.top  = topOffset;
16337             
16338             switch (this.align) {
16339                 case 'stretch':
16340                     stretchWidth = availWidth - horizMargins;
16341                     calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
16342                     calcs.dirtySize = true;
16343                     break;
16344                 case 'stretchmax':
16345                     stretchWidth = maxWidth - horizMargins;
16346                     calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
16347                     calcs.dirtySize = true;
16348                     break;
16349                 case 'center':
16350                     var diff = availWidth - calcs.width - horizMargins;
16351                     if (diff > 0) {
16352                         calcs.left = leftOffset + horizMargins + (diff / 2);
16353                     }
16354             }
16355
16356             topOffset += calcs.height + childMargins.bottom;
16357         }
16358         
16359         return {
16360             boxes: boxes,
16361             meta : {
16362                 maxWidth     : maxWidth,
16363                 nonFlexHeight: nonFlexHeight,
16364                 desiredHeight: desiredHeight,
16365                 minimumHeight: minimumHeight,
16366                 shortfall    : desiredHeight - height,
16367                 tooNarrow    : tooNarrow
16368             }
16369         };
16370     }
16371 });
16372
16373 Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
16374
16375 Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {
16376     monitorResize : true,
16377
16378     type: 'toolbar',
16379
16380     
16381     triggerWidth: 18,
16382
16383     
16384     noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
16385
16386     
16387     lastOverflow: false,
16388
16389     
16390     tableHTML: [
16391         '<table cellspacing="0" class="x-toolbar-ct">',
16392             '<tbody>',
16393                 '<tr>',
16394                     '<td class="x-toolbar-left" align="{0}">',
16395                         '<table cellspacing="0">',
16396                             '<tbody>',
16397                                 '<tr class="x-toolbar-left-row"></tr>',
16398                             '</tbody>',
16399                         '</table>',
16400                     '</td>',
16401                     '<td class="x-toolbar-right" align="right">',
16402                         '<table cellspacing="0" class="x-toolbar-right-ct">',
16403                             '<tbody>',
16404                                 '<tr>',
16405                                     '<td>',
16406                                         '<table cellspacing="0">',
16407                                             '<tbody>',
16408                                                 '<tr class="x-toolbar-right-row"></tr>',
16409                                             '</tbody>',
16410                                         '</table>',
16411                                     '</td>',
16412                                     '<td>',
16413                                         '<table cellspacing="0">',
16414                                             '<tbody>',
16415                                                 '<tr class="x-toolbar-extras-row"></tr>',
16416                                             '</tbody>',
16417                                         '</table>',
16418                                     '</td>',
16419                                 '</tr>',
16420                             '</tbody>',
16421                         '</table>',
16422                     '</td>',
16423                 '</tr>',
16424             '</tbody>',
16425         '</table>'
16426     ].join(""),
16427
16428     
16429     onLayout : function(ct, target) {
16430         
16431         if (!this.leftTr) {
16432             var align = ct.buttonAlign == 'center' ? 'center' : 'left';
16433
16434             target.addClass('x-toolbar-layout-ct');
16435             target.insertHtml('beforeEnd', String.format(this.tableHTML, align));
16436
16437             this.leftTr   = target.child('tr.x-toolbar-left-row', true);
16438             this.rightTr  = target.child('tr.x-toolbar-right-row', true);
16439             this.extrasTr = target.child('tr.x-toolbar-extras-row', true);
16440
16441             if (this.hiddenItem == undefined) {
16442                 
16443                 this.hiddenItems = [];
16444             }
16445         }
16446
16447         var side     = ct.buttonAlign == 'right' ? this.rightTr : this.leftTr,
16448             items    = ct.items.items,
16449             position = 0;
16450
16451         
16452         for (var i = 0, len = items.length, c; i < len; i++, position++) {
16453             c = items[i];
16454
16455             if (c.isFill) {
16456                 side   = this.rightTr;
16457                 position = -1;
16458             } else if (!c.rendered) {
16459                 c.render(this.insertCell(c, side, position));
16460                 this.configureItem(c);
16461             } else {
16462                 if (!c.xtbHidden && !this.isValidParent(c, side.childNodes[position])) {
16463                     var td = this.insertCell(c, side, position);
16464                     td.appendChild(c.getPositionEl().dom);
16465                     c.container = Ext.get(td);
16466                 }
16467             }
16468         }
16469
16470         
16471         this.cleanup(this.leftTr);
16472         this.cleanup(this.rightTr);
16473         this.cleanup(this.extrasTr);
16474         this.fitToSize(target);
16475     },
16476
16477     
16478     cleanup : function(el) {
16479         var cn = el.childNodes, i, c;
16480
16481         for (i = cn.length-1; i >= 0 && (c = cn[i]); i--) {
16482             if (!c.firstChild) {
16483                 el.removeChild(c);
16484             }
16485         }
16486     },
16487
16488     
16489     insertCell : function(c, target, position) {
16490         var td = document.createElement('td');
16491         td.className = 'x-toolbar-cell';
16492
16493         target.insertBefore(td, target.childNodes[position] || null);
16494
16495         return td;
16496     },
16497
16498     
16499     hideItem : function(item) {
16500         this.hiddenItems.push(item);
16501
16502         item.xtbHidden = true;
16503         item.xtbWidth = item.getPositionEl().dom.parentNode.offsetWidth;
16504         item.hide();
16505     },
16506
16507     
16508     unhideItem : function(item) {
16509         item.show();
16510         item.xtbHidden = false;
16511         this.hiddenItems.remove(item);
16512     },
16513
16514     
16515     getItemWidth : function(c) {
16516         return c.hidden ? (c.xtbWidth || 0) : c.getPositionEl().dom.parentNode.offsetWidth;
16517     },
16518
16519     
16520     fitToSize : function(target) {
16521         if (this.container.enableOverflow === false) {
16522             return;
16523         }
16524
16525         var width       = target.dom.clientWidth,
16526             tableWidth  = target.dom.firstChild.offsetWidth,
16527             clipWidth   = width - this.triggerWidth,
16528             lastWidth   = this.lastWidth || 0,
16529
16530             hiddenItems = this.hiddenItems,
16531             hasHiddens  = hiddenItems.length != 0,
16532             isLarger    = width >= lastWidth;
16533
16534         this.lastWidth  = width;
16535
16536         if (tableWidth > width || (hasHiddens && isLarger)) {
16537             var items     = this.container.items.items,
16538                 len       = items.length,
16539                 loopWidth = 0,
16540                 item;
16541
16542             for (var i = 0; i < len; i++) {
16543                 item = items[i];
16544
16545                 if (!item.isFill) {
16546                     loopWidth += this.getItemWidth(item);
16547                     if (loopWidth > clipWidth) {
16548                         if (!(item.hidden || item.xtbHidden)) {
16549                             this.hideItem(item);
16550                         }
16551                     } else if (item.xtbHidden) {
16552                         this.unhideItem(item);
16553                     }
16554                 }
16555             }
16556         }
16557
16558         
16559         hasHiddens = hiddenItems.length != 0;
16560
16561         if (hasHiddens) {
16562             this.initMore();
16563
16564             if (!this.lastOverflow) {
16565                 this.container.fireEvent('overflowchange', this.container, true);
16566                 this.lastOverflow = true;
16567             }
16568         } else if (this.more) {
16569             this.clearMenu();
16570             this.more.destroy();
16571             delete this.more;
16572
16573             if (this.lastOverflow) {
16574                 this.container.fireEvent('overflowchange', this.container, false);
16575                 this.lastOverflow = false;
16576             }
16577         }
16578     },
16579
16580     
16581     createMenuConfig : function(component, hideOnClick){
16582         var config = Ext.apply({}, component.initialConfig),
16583             group  = component.toggleGroup;
16584
16585         Ext.copyTo(config, component, [
16586             'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
16587         ]);
16588
16589         Ext.apply(config, {
16590             text       : component.overflowText || component.text,
16591             hideOnClick: hideOnClick
16592         });
16593
16594         if (group || component.enableToggle) {
16595             Ext.apply(config, {
16596                 group  : group,
16597                 checked: component.pressed,
16598                 listeners: {
16599                     checkchange: function(item, checked){
16600                         component.toggle(checked);
16601                     }
16602                 }
16603             });
16604         }
16605
16606         delete config.ownerCt;
16607         delete config.xtype;
16608         delete config.id;
16609
16610         return config;
16611     },
16612
16613     
16614     addComponentToMenu : function(menu, component) {
16615         if (component instanceof Ext.Toolbar.Separator) {
16616             menu.add('-');
16617
16618         } else if (Ext.isFunction(component.isXType)) {
16619             if (component.isXType('splitbutton')) {
16620                 menu.add(this.createMenuConfig(component, true));
16621
16622             } else if (component.isXType('button')) {
16623                 menu.add(this.createMenuConfig(component, !component.menu));
16624
16625             } else if (component.isXType('buttongroup')) {
16626                 component.items.each(function(item){
16627                      this.addComponentToMenu(menu, item);
16628                 }, this);
16629             }
16630         }
16631     },
16632
16633     
16634     clearMenu : function(){
16635         var menu = this.moreMenu;
16636         if (menu && menu.items) {
16637             menu.items.each(function(item){
16638                 delete item.menu;
16639             });
16640         }
16641     },
16642
16643     
16644     beforeMoreShow : function(menu) {
16645         var items = this.container.items.items,
16646             len   = items.length,
16647             item,
16648             prev;
16649
16650         var needsSep = function(group, item){
16651             return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
16652         };
16653
16654         this.clearMenu();
16655         menu.removeAll();
16656         for (var i = 0; i < len; i++) {
16657             item = items[i];
16658             if (item.xtbHidden) {
16659                 if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
16660                     menu.add('-');
16661                 }
16662                 this.addComponentToMenu(menu, item);
16663                 prev = item;
16664             }
16665         }
16666
16667         
16668         if (menu.items.length < 1) {
16669             menu.add(this.noItemsMenuText);
16670         }
16671     },
16672
16673     
16674     initMore : function(){
16675         if (!this.more) {
16676             
16677             this.moreMenu = new Ext.menu.Menu({
16678                 ownerCt : this.container,
16679                 listeners: {
16680                     beforeshow: this.beforeMoreShow,
16681                     scope: this
16682                 }
16683             });
16684
16685             
16686             this.more = new Ext.Button({
16687                 iconCls: 'x-toolbar-more-icon',
16688                 cls    : 'x-toolbar-more',
16689                 menu   : this.moreMenu,
16690                 ownerCt: this.container
16691             });
16692
16693             var td = this.insertCell(this.more, this.extrasTr, 100);
16694             this.more.render(td);
16695         }
16696     },
16697
16698     destroy : function(){
16699         Ext.destroy(this.more, this.moreMenu);
16700         delete this.leftTr;
16701         delete this.rightTr;
16702         delete this.extrasTr;
16703         Ext.layout.ToolbarLayout.superclass.destroy.call(this);
16704     }
16705 });
16706
16707 Ext.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;
16708
16709  Ext.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {
16710     monitorResize : true,
16711
16712     type: 'menu',
16713
16714     setContainer : function(ct){
16715         this.monitorResize = !ct.floating;
16716         
16717         
16718         ct.on('autosize', this.doAutoSize, this);
16719         Ext.layout.MenuLayout.superclass.setContainer.call(this, ct);
16720     },
16721
16722     renderItem : function(c, position, target){
16723         if (!this.itemTpl) {
16724             this.itemTpl = Ext.layout.MenuLayout.prototype.itemTpl = new Ext.XTemplate(
16725                 '<li id="{itemId}" class="{itemCls}">',
16726                     '<tpl if="needsIcon">',
16727                         '<img alt="{altText}" src="{icon}" class="{iconCls}"/>',
16728                     '</tpl>',
16729                 '</li>'
16730             );
16731         }
16732
16733         if(c && !c.rendered){
16734             if(Ext.isNumber(position)){
16735                 position = target.dom.childNodes[position];
16736             }
16737             var a = this.getItemArgs(c);
16738
16739
16740             c.render(c.positionEl = position ?
16741                 this.itemTpl.insertBefore(position, a, true) :
16742                 this.itemTpl.append(target, a, true));
16743
16744
16745             c.positionEl.menuItemId = c.getItemId();
16746
16747
16748
16749             if (!a.isMenuItem && a.needsIcon) {
16750                 c.positionEl.addClass('x-menu-list-item-indent');
16751             }
16752             this.configureItem(c);
16753         }else if(c && !this.isValidParent(c, target)){
16754             if(Ext.isNumber(position)){
16755                 position = target.dom.childNodes[position];
16756             }
16757             target.dom.insertBefore(c.getActionEl().dom, position || null);
16758         }
16759     },
16760
16761     getItemArgs : function(c) {
16762         var isMenuItem = c instanceof Ext.menu.Item,
16763             canHaveIcon = !(isMenuItem || c instanceof Ext.menu.Separator);
16764
16765         return {
16766             isMenuItem: isMenuItem,
16767             needsIcon: canHaveIcon && (c.icon || c.iconCls),
16768             icon: c.icon || Ext.BLANK_IMAGE_URL,
16769             iconCls: 'x-menu-item-icon ' + (c.iconCls || ''),
16770             itemId: 'x-menu-el-' + c.id,
16771             itemCls: 'x-menu-list-item ',
16772             altText: c.altText || ''
16773         };
16774     },
16775
16776     
16777     isValidParent : function(c, target) {
16778         return c.el.up('li.x-menu-list-item', 5).dom.parentNode === (target.dom || target);
16779     },
16780
16781     onLayout : function(ct, target){
16782         Ext.layout.MenuLayout.superclass.onLayout.call(this, ct, target);
16783         this.doAutoSize();
16784     },
16785
16786     doAutoSize : function(){
16787         var ct = this.container, w = ct.width;
16788         if(ct.floating){
16789             if(w){
16790                 ct.setWidth(w);
16791             }else if(Ext.isIE){
16792                 ct.setWidth(Ext.isStrict && (Ext.isIE7 || Ext.isIE8) ? 'auto' : ct.minWidth);
16793                 var el = ct.getEl(), t = el.dom.offsetWidth; 
16794                 ct.setWidth(ct.getLayoutTarget().getWidth() + el.getFrameWidth('lr'));
16795             }
16796         }
16797     }
16798 });
16799 Ext.Container.LAYOUTS['menu'] = Ext.layout.MenuLayout;
16800
16801 Ext.Viewport = Ext.extend(Ext.Container, {
16802     
16803     
16804     
16805     
16806     
16807     
16808     
16809     
16810     
16811     
16812     
16813     
16814
16815     initComponent : function() {
16816         Ext.Viewport.superclass.initComponent.call(this);
16817         document.getElementsByTagName('html')[0].className += ' x-viewport';
16818         this.el = Ext.getBody();
16819         this.el.setHeight = Ext.emptyFn;
16820         this.el.setWidth = Ext.emptyFn;
16821         this.el.setSize = Ext.emptyFn;
16822         this.el.dom.scroll = 'no';
16823         this.allowDomMove = false;
16824         this.autoWidth = true;
16825         this.autoHeight = true;
16826         Ext.EventManager.onWindowResize(this.fireResize, this);
16827         this.renderTo = this.el;
16828     },
16829
16830     fireResize : function(w, h){
16831         this.fireEvent('resize', this, w, h, w, h);
16832     }
16833 });
16834 Ext.reg('viewport', Ext.Viewport);
16835
16836 Ext.Panel = Ext.extend(Ext.Container, {
16837     
16838     
16839     
16840     
16841     
16842     
16843     
16844     
16845     
16846     
16847     
16848     
16849     
16850     
16851     
16852     
16853     
16854     
16855     
16856     
16857     
16858     
16859     
16860     
16861     
16862     
16863     
16864     
16865     
16866     
16867     
16868     
16869
16870     
16871     
16872     
16873     
16874     
16875     
16876     
16877     
16878
16879
16880     
16881     baseCls : 'x-panel',
16882     
16883     collapsedCls : 'x-panel-collapsed',
16884     
16885     maskDisabled : true,
16886     
16887     animCollapse : Ext.enableFx,
16888     
16889     headerAsText : true,
16890     
16891     buttonAlign : 'right',
16892     
16893     collapsed : false,
16894     
16895     collapseFirst : true,
16896     
16897     minButtonWidth : 75,
16898     
16899     
16900     elements : 'body',
16901     
16902     preventBodyReset : false,
16903
16904     
16905     padding: undefined,
16906
16907     
16908     resizeEvent: 'bodyresize',
16909
16910     
16911     
16912     
16913     toolTarget : 'header',
16914     collapseEl : 'bwrap',
16915     slideAnchor : 't',
16916     disabledClass : '',
16917
16918     
16919     deferHeight : true,
16920     
16921     expandDefaults: {
16922         duration : 0.25
16923     },
16924     
16925     collapseDefaults : {
16926         duration : 0.25
16927     },
16928
16929     
16930     initComponent : function(){
16931         Ext.Panel.superclass.initComponent.call(this);
16932
16933         this.addEvents(
16934             
16935             'bodyresize',
16936             
16937             'titlechange',
16938             
16939             'iconchange',
16940             
16941             'collapse',
16942             
16943             'expand',
16944             
16945             'beforecollapse',
16946             
16947             'beforeexpand',
16948             
16949             'beforeclose',
16950             
16951             'close',
16952             
16953             'activate',
16954             
16955             'deactivate'
16956         );
16957
16958         if(this.unstyled){
16959             this.baseCls = 'x-plain';
16960         }
16961
16962
16963         this.toolbars = [];
16964         
16965         if(this.tbar){
16966             this.elements += ',tbar';
16967             this.topToolbar = this.createToolbar(this.tbar);
16968             this.tbar = null;
16969
16970         }
16971         if(this.bbar){
16972             this.elements += ',bbar';
16973             this.bottomToolbar = this.createToolbar(this.bbar);
16974             this.bbar = null;
16975         }
16976
16977         if(this.header === true){
16978             this.elements += ',header';
16979             this.header = null;
16980         }else if(this.headerCfg || (this.title && this.header !== false)){
16981             this.elements += ',header';
16982         }
16983
16984         if(this.footerCfg || this.footer === true){
16985             this.elements += ',footer';
16986             this.footer = null;
16987         }
16988
16989         if(this.buttons){
16990             this.fbar = this.buttons;
16991             this.buttons = null;
16992         }
16993         if(this.fbar){
16994             this.createFbar(this.fbar);
16995         }
16996         if(this.autoLoad){
16997             this.on('render', this.doAutoLoad, this, {delay:10});
16998         }
16999     },
17000
17001     
17002     createFbar : function(fbar){
17003         var min = this.minButtonWidth;
17004         this.elements += ',footer';
17005         this.fbar = this.createToolbar(fbar, {
17006             buttonAlign: this.buttonAlign,
17007             toolbarCls: 'x-panel-fbar',
17008             enableOverflow: false,
17009             defaults: function(c){
17010                 return {
17011                     minWidth: c.minWidth || min
17012                 };
17013             }
17014         });
17015         
17016         
17017         
17018         this.fbar.items.each(function(c){
17019             c.minWidth = c.minWidth || this.minButtonWidth;
17020         }, this);
17021         this.buttons = this.fbar.items.items;
17022     },
17023
17024     
17025     createToolbar: function(tb, options){
17026         var result;
17027         
17028         if(Ext.isArray(tb)){
17029             tb = {
17030                 items: tb
17031             };
17032         }
17033         result = tb.events ? Ext.apply(tb, options) : this.createComponent(Ext.apply({}, tb, options), 'toolbar');
17034         this.toolbars.push(result);
17035         return result;
17036     },
17037
17038     
17039     createElement : function(name, pnode){
17040         if(this[name]){
17041             pnode.appendChild(this[name].dom);
17042             return;
17043         }
17044
17045         if(name === 'bwrap' || this.elements.indexOf(name) != -1){
17046             if(this[name+'Cfg']){
17047                 this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
17048             }else{
17049                 var el = document.createElement('div');
17050                 el.className = this[name+'Cls'];
17051                 this[name] = Ext.get(pnode.appendChild(el));
17052             }
17053             if(this[name+'CssClass']){
17054                 this[name].addClass(this[name+'CssClass']);
17055             }
17056             if(this[name+'Style']){
17057                 this[name].applyStyles(this[name+'Style']);
17058             }
17059         }
17060     },
17061
17062     
17063     onRender : function(ct, position){
17064         Ext.Panel.superclass.onRender.call(this, ct, position);
17065         this.createClasses();
17066
17067         var el = this.el,
17068             d = el.dom,
17069             bw,
17070             ts;
17071
17072
17073         if(this.collapsible && !this.hideCollapseTool){
17074             this.tools = this.tools ? this.tools.slice(0) : [];
17075             this.tools[this.collapseFirst?'unshift':'push']({
17076                 id: 'toggle',
17077                 handler : this.toggleCollapse,
17078                 scope: this
17079             });
17080         }
17081
17082         if(this.tools){
17083             ts = this.tools;
17084             this.elements += (this.header !== false) ? ',header' : '';
17085         }
17086         this.tools = {};
17087
17088         el.addClass(this.baseCls);
17089         if(d.firstChild){ 
17090             this.header = el.down('.'+this.headerCls);
17091             this.bwrap = el.down('.'+this.bwrapCls);
17092             var cp = this.bwrap ? this.bwrap : el;
17093             this.tbar = cp.down('.'+this.tbarCls);
17094             this.body = cp.down('.'+this.bodyCls);
17095             this.bbar = cp.down('.'+this.bbarCls);
17096             this.footer = cp.down('.'+this.footerCls);
17097             this.fromMarkup = true;
17098         }
17099         if (this.preventBodyReset === true) {
17100             el.addClass('x-panel-reset');
17101         }
17102         if(this.cls){
17103             el.addClass(this.cls);
17104         }
17105
17106         if(this.buttons){
17107             this.elements += ',footer';
17108         }
17109
17110         
17111
17112         
17113         if(this.frame){
17114             el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
17115
17116             this.createElement('header', d.firstChild.firstChild.firstChild);
17117             this.createElement('bwrap', d);
17118
17119             
17120             bw = this.bwrap.dom;
17121             var ml = d.childNodes[1], bl = d.childNodes[2];
17122             bw.appendChild(ml);
17123             bw.appendChild(bl);
17124
17125             var mc = bw.firstChild.firstChild.firstChild;
17126             this.createElement('tbar', mc);
17127             this.createElement('body', mc);
17128             this.createElement('bbar', mc);
17129             this.createElement('footer', bw.lastChild.firstChild.firstChild);
17130
17131             if(!this.footer){
17132                 this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
17133             }
17134             
17135             this.ft = Ext.get(this.bwrap.dom.lastChild);
17136             this.mc = Ext.get(mc);
17137         }else{
17138             this.createElement('header', d);
17139             this.createElement('bwrap', d);
17140
17141             
17142             bw = this.bwrap.dom;
17143             this.createElement('tbar', bw);
17144             this.createElement('body', bw);
17145             this.createElement('bbar', bw);
17146             this.createElement('footer', bw);
17147
17148             if(!this.header){
17149                 this.body.addClass(this.bodyCls + '-noheader');
17150                 if(this.tbar){
17151                     this.tbar.addClass(this.tbarCls + '-noheader');
17152                 }
17153             }
17154         }
17155
17156         if(Ext.isDefined(this.padding)){
17157             this.body.setStyle('padding', this.body.addUnits(this.padding));
17158         }
17159
17160         if(this.border === false){
17161             this.el.addClass(this.baseCls + '-noborder');
17162             this.body.addClass(this.bodyCls + '-noborder');
17163             if(this.header){
17164                 this.header.addClass(this.headerCls + '-noborder');
17165             }
17166             if(this.footer){
17167                 this.footer.addClass(this.footerCls + '-noborder');
17168             }
17169             if(this.tbar){
17170                 this.tbar.addClass(this.tbarCls + '-noborder');
17171             }
17172             if(this.bbar){
17173                 this.bbar.addClass(this.bbarCls + '-noborder');
17174             }
17175         }
17176
17177         if(this.bodyBorder === false){
17178            this.body.addClass(this.bodyCls + '-noborder');
17179         }
17180
17181         this.bwrap.enableDisplayMode('block');
17182
17183         if(this.header){
17184             this.header.unselectable();
17185
17186             
17187             if(this.headerAsText){
17188                 this.header.dom.innerHTML =
17189                     '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
17190
17191                 if(this.iconCls){
17192                     this.setIconClass(this.iconCls);
17193                 }
17194             }
17195         }
17196
17197         if(this.floating){
17198             this.makeFloating(this.floating);
17199         }
17200
17201         if(this.collapsible && this.titleCollapse && this.header){
17202             this.mon(this.header, 'click', this.toggleCollapse, this);
17203             this.header.setStyle('cursor', 'pointer');
17204         }
17205         if(ts){
17206             this.addTool.apply(this, ts);
17207         }
17208
17209         
17210         if(this.fbar){
17211             this.footer.addClass('x-panel-btns');
17212             this.fbar.ownerCt = this;
17213             this.fbar.render(this.footer);
17214             this.footer.createChild({cls:'x-clear'});
17215         }
17216         if(this.tbar && this.topToolbar){
17217             this.topToolbar.ownerCt = this;
17218             this.topToolbar.render(this.tbar);
17219         }
17220         if(this.bbar && this.bottomToolbar){
17221             this.bottomToolbar.ownerCt = this;
17222             this.bottomToolbar.render(this.bbar);
17223         }
17224     },
17225
17226     
17227     setIconClass : function(cls){
17228         var old = this.iconCls;
17229         this.iconCls = cls;
17230         if(this.rendered && this.header){
17231             if(this.frame){
17232                 this.header.addClass('x-panel-icon');
17233                 this.header.replaceClass(old, this.iconCls);
17234             }else{
17235                 var hd = this.header,
17236                     img = hd.child('img.x-panel-inline-icon');
17237                 if(img){
17238                     Ext.fly(img).replaceClass(old, this.iconCls);
17239                 }else{
17240                     var hdspan = hd.child('span.' + this.headerTextCls);
17241                     if (hdspan) {
17242                         Ext.DomHelper.insertBefore(hdspan.dom, {
17243                             tag:'img', alt: '', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
17244                         });
17245                     }
17246                  }
17247             }
17248         }
17249         this.fireEvent('iconchange', this, cls, old);
17250     },
17251
17252     
17253     makeFloating : function(cfg){
17254         this.floating = true;
17255         this.el = new Ext.Layer(Ext.apply({}, cfg, {
17256             shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
17257             shadowOffset: this.shadowOffset,
17258             constrain:false,
17259             shim: this.shim === false ? false : undefined
17260         }), this.el);
17261     },
17262
17263     
17264     getTopToolbar : function(){
17265         return this.topToolbar;
17266     },
17267
17268     
17269     getBottomToolbar : function(){
17270         return this.bottomToolbar;
17271     },
17272
17273     
17274     getFooterToolbar : function() {
17275         return this.fbar;
17276     },
17277
17278     
17279     addButton : function(config, handler, scope){
17280         if(!this.fbar){
17281             this.createFbar([]);
17282         }
17283         if(handler){
17284             if(Ext.isString(config)){
17285                 config = {text: config};
17286             }
17287             config = Ext.apply({
17288                 handler: handler,
17289                 scope: scope
17290             }, config);
17291         }
17292         return this.fbar.add(config);
17293     },
17294
17295     
17296     addTool : function(){
17297         if(!this.rendered){
17298             if(!this.tools){
17299                 this.tools = [];
17300             }
17301             Ext.each(arguments, function(arg){
17302                 this.tools.push(arg);
17303             }, this);
17304             return;
17305         }
17306          
17307         if(!this[this.toolTarget]){
17308             return;
17309         }
17310         if(!this.toolTemplate){
17311             
17312             var tt = new Ext.Template(
17313                  '<div class="x-tool x-tool-{id}">&#160;</div>'
17314             );
17315             tt.disableFormats = true;
17316             tt.compile();
17317             Ext.Panel.prototype.toolTemplate = tt;
17318         }
17319         for(var i = 0, a = arguments, len = a.length; i < len; i++) {
17320             var tc = a[i];
17321             if(!this.tools[tc.id]){
17322                 var overCls = 'x-tool-'+tc.id+'-over';
17323                 var t = this.toolTemplate.insertFirst(this[this.toolTarget], tc, true);
17324                 this.tools[tc.id] = t;
17325                 t.enableDisplayMode('block');
17326                 this.mon(t, 'click',  this.createToolHandler(t, tc, overCls, this));
17327                 if(tc.on){
17328                     this.mon(t, tc.on);
17329                 }
17330                 if(tc.hidden){
17331                     t.hide();
17332                 }
17333                 if(tc.qtip){
17334                     if(Ext.isObject(tc.qtip)){
17335                         Ext.QuickTips.register(Ext.apply({
17336                               target: t.id
17337                         }, tc.qtip));
17338                     } else {
17339                         t.dom.qtip = tc.qtip;
17340                     }
17341                 }
17342                 t.addClassOnOver(overCls);
17343             }
17344         }
17345     },
17346
17347     onLayout : function(shallow, force){
17348         Ext.Panel.superclass.onLayout.apply(this, arguments);
17349         if(this.hasLayout && this.toolbars.length > 0){
17350             Ext.each(this.toolbars, function(tb){
17351                 tb.doLayout(undefined, force);
17352             });
17353             this.syncHeight();
17354         }
17355     },
17356
17357     syncHeight : function(){
17358         var h = this.toolbarHeight,
17359                 bd = this.body,
17360                 lsh = this.lastSize.height,
17361                 sz;
17362
17363         if(this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto'){
17364             return;
17365         }
17366
17367
17368         if(h != this.getToolbarHeight()){
17369             h = Math.max(0, lsh - this.getFrameHeight());
17370             bd.setHeight(h);
17371             sz = bd.getSize();
17372             this.toolbarHeight = this.getToolbarHeight();
17373             this.onBodyResize(sz.width, sz.height);
17374         }
17375     },
17376
17377     
17378     onShow : function(){
17379         if(this.floating){
17380             return this.el.show();
17381         }
17382         Ext.Panel.superclass.onShow.call(this);
17383     },
17384
17385     
17386     onHide : function(){
17387         if(this.floating){
17388             return this.el.hide();
17389         }
17390         Ext.Panel.superclass.onHide.call(this);
17391     },
17392
17393     
17394     createToolHandler : function(t, tc, overCls, panel){
17395         return function(e){
17396             t.removeClass(overCls);
17397             if(tc.stopEvent !== false){
17398                 e.stopEvent();
17399             }
17400             if(tc.handler){
17401                 tc.handler.call(tc.scope || t, e, t, panel, tc);
17402             }
17403         };
17404     },
17405
17406     
17407     afterRender : function(){
17408         if(this.floating && !this.hidden){
17409             this.el.show();
17410         }
17411         if(this.title){
17412             this.setTitle(this.title);
17413         }
17414         Ext.Panel.superclass.afterRender.call(this); 
17415         if (this.collapsed) {
17416             this.collapsed = false;
17417             this.collapse(false);
17418         }
17419         this.initEvents();
17420     },
17421
17422     
17423     getKeyMap : function(){
17424         if(!this.keyMap){
17425             this.keyMap = new Ext.KeyMap(this.el, this.keys);
17426         }
17427         return this.keyMap;
17428     },
17429
17430     
17431     initEvents : function(){
17432         if(this.keys){
17433             this.getKeyMap();
17434         }
17435         if(this.draggable){
17436             this.initDraggable();
17437         }
17438         if(this.toolbars.length > 0){
17439             Ext.each(this.toolbars, function(tb){
17440                 tb.doLayout();
17441                 tb.on({
17442                     scope: this,
17443                     afterlayout: this.syncHeight,
17444                     remove: this.syncHeight
17445                 });
17446             }, this);
17447             this.syncHeight();
17448         }
17449
17450     },
17451
17452     
17453     initDraggable : function(){
17454         
17455         this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable);
17456     },
17457
17458     
17459     beforeEffect : function(anim){
17460         if(this.floating){
17461             this.el.beforeAction();
17462         }
17463         if(anim !== false){
17464             this.el.addClass('x-panel-animated');
17465         }
17466     },
17467
17468     
17469     afterEffect : function(anim){
17470         this.syncShadow();
17471         this.el.removeClass('x-panel-animated');
17472     },
17473
17474     
17475     createEffect : function(a, cb, scope){
17476         var o = {
17477             scope:scope,
17478             block:true
17479         };
17480         if(a === true){
17481             o.callback = cb;
17482             return o;
17483         }else if(!a.callback){
17484             o.callback = cb;
17485         }else { 
17486             o.callback = function(){
17487                 cb.call(scope);
17488                 Ext.callback(a.callback, a.scope);
17489             };
17490         }
17491         return Ext.applyIf(o, a);
17492     },
17493
17494     
17495     collapse : function(animate){
17496         if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
17497             return;
17498         }
17499         var doAnim = animate === true || (animate !== false && this.animCollapse);
17500         this.beforeEffect(doAnim);
17501         this.onCollapse(doAnim, animate);
17502         return this;
17503     },
17504
17505     
17506     onCollapse : function(doAnim, animArg){
17507         if(doAnim){
17508             this[this.collapseEl].slideOut(this.slideAnchor,
17509                     Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
17510                         this.collapseDefaults));
17511         }else{
17512             this[this.collapseEl].hide(this.hideMode);
17513             this.afterCollapse(false);
17514         }
17515     },
17516
17517     
17518     afterCollapse : function(anim){
17519         this.collapsed = true;
17520         this.el.addClass(this.collapsedCls);
17521         if(anim !== false){
17522             this[this.collapseEl].hide(this.hideMode);
17523         }
17524         this.afterEffect(anim);
17525
17526         
17527         this.cascade(function(c) {
17528             if (c.lastSize) {
17529                 c.lastSize = { width: undefined, height: undefined };
17530             }
17531         });
17532         this.fireEvent('collapse', this);
17533     },
17534
17535     
17536     expand : function(animate){
17537         if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
17538             return;
17539         }
17540         var doAnim = animate === true || (animate !== false && this.animCollapse);
17541         this.el.removeClass(this.collapsedCls);
17542         this.beforeEffect(doAnim);
17543         this.onExpand(doAnim, animate);
17544         return this;
17545     },
17546
17547     
17548     onExpand : function(doAnim, animArg){
17549         if(doAnim){
17550             this[this.collapseEl].slideIn(this.slideAnchor,
17551                     Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
17552                         this.expandDefaults));
17553         }else{
17554             this[this.collapseEl].show(this.hideMode);
17555             this.afterExpand(false);
17556         }
17557     },
17558
17559     
17560     afterExpand : function(anim){
17561         this.collapsed = false;
17562         if(anim !== false){
17563             this[this.collapseEl].show(this.hideMode);
17564         }
17565         this.afterEffect(anim);
17566         if (this.deferLayout) {
17567             delete this.deferLayout;
17568             this.doLayout(true);
17569         }
17570         this.fireEvent('expand', this);
17571     },
17572
17573     
17574     toggleCollapse : function(animate){
17575         this[this.collapsed ? 'expand' : 'collapse'](animate);
17576         return this;
17577     },
17578
17579     
17580     onDisable : function(){
17581         if(this.rendered && this.maskDisabled){
17582             this.el.mask();
17583         }
17584         Ext.Panel.superclass.onDisable.call(this);
17585     },
17586
17587     
17588     onEnable : function(){
17589         if(this.rendered && this.maskDisabled){
17590             this.el.unmask();
17591         }
17592         Ext.Panel.superclass.onEnable.call(this);
17593     },
17594
17595     
17596     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
17597         var w = adjWidth,
17598             h = adjHeight;
17599
17600         if(Ext.isDefined(w) || Ext.isDefined(h)){
17601             if(!this.collapsed){
17602                 
17603                 
17604                 
17605
17606                 if(Ext.isNumber(w)){
17607                     this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
17608                 } else if (w == 'auto') {
17609                     w = this.body.setWidth('auto').dom.offsetWidth;
17610                 } else {
17611                     w = this.body.dom.offsetWidth;
17612                 }
17613
17614                 if(this.tbar){
17615                     this.tbar.setWidth(w);
17616                     if(this.topToolbar){
17617                         this.topToolbar.setSize(w);
17618                     }
17619                 }
17620                 if(this.bbar){
17621                     this.bbar.setWidth(w);
17622                     if(this.bottomToolbar){
17623                         this.bottomToolbar.setSize(w);
17624                         
17625                         if (Ext.isIE) {
17626                             this.bbar.setStyle('position', 'static');
17627                             this.bbar.setStyle('position', '');
17628                         }
17629                     }
17630                 }
17631                 if(this.footer){
17632                     this.footer.setWidth(w);
17633                     if(this.fbar){
17634                         this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
17635                     }
17636                 }
17637
17638                 
17639                 if(Ext.isNumber(h)){
17640                     h = Math.max(0, h - this.getFrameHeight());
17641                     
17642                     this.body.setHeight(h);
17643                 }else if(h == 'auto'){
17644                     this.body.setHeight(h);
17645                 }
17646
17647                 if(this.disabled && this.el._mask){
17648                     this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
17649                 }
17650             }else{
17651                 
17652                 this.queuedBodySize = {width: w, height: h};
17653                 if(!this.queuedExpand && this.allowQueuedExpand !== false){
17654                     this.queuedExpand = true;
17655                     this.on('expand', function(){
17656                         delete this.queuedExpand;
17657                         this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
17658                     }, this, {single:true});
17659                 }
17660             }
17661             this.onBodyResize(w, h);
17662         }
17663         this.syncShadow();
17664         Ext.Panel.superclass.onResize.call(this, adjWidth, adjHeight, rawWidth, rawHeight);
17665
17666     },
17667
17668     
17669     onBodyResize: function(w, h){
17670         this.fireEvent('bodyresize', this, w, h);
17671     },
17672
17673     
17674     getToolbarHeight: function(){
17675         var h = 0;
17676         if(this.rendered){
17677             Ext.each(this.toolbars, function(tb){
17678                 h += tb.getHeight();
17679             }, this);
17680         }
17681         return h;
17682     },
17683
17684     
17685     adjustBodyHeight : function(h){
17686         return h;
17687     },
17688
17689     
17690     adjustBodyWidth : function(w){
17691         return w;
17692     },
17693
17694     
17695     onPosition : function(){
17696         this.syncShadow();
17697     },
17698
17699     
17700     getFrameWidth : function(){
17701         var w = this.el.getFrameWidth('lr') + this.bwrap.getFrameWidth('lr');
17702
17703         if(this.frame){
17704             var l = this.bwrap.dom.firstChild;
17705             w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
17706             w += this.mc.getFrameWidth('lr');
17707         }
17708         return w;
17709     },
17710
17711     
17712     getFrameHeight : function() {
17713         var h  = this.el.getFrameWidth('tb') + this.bwrap.getFrameWidth('tb');
17714         h += (this.tbar ? this.tbar.getHeight() : 0) +
17715              (this.bbar ? this.bbar.getHeight() : 0);
17716
17717         if(this.frame){
17718             h += this.el.dom.firstChild.offsetHeight + this.ft.dom.offsetHeight + this.mc.getFrameWidth('tb');
17719         }else{
17720             h += (this.header ? this.header.getHeight() : 0) +
17721                 (this.footer ? this.footer.getHeight() : 0);
17722         }
17723         return h;
17724     },
17725
17726     
17727     getInnerWidth : function(){
17728         return this.getSize().width - this.getFrameWidth();
17729     },
17730
17731     
17732     getInnerHeight : function(){
17733         return this.body.getHeight();
17734         
17735     },
17736
17737     
17738     syncShadow : function(){
17739         if(this.floating){
17740             this.el.sync(true);
17741         }
17742     },
17743
17744     
17745     getLayoutTarget : function(){
17746         return this.body;
17747     },
17748
17749     
17750     getContentTarget : function(){
17751         return this.body;
17752     },
17753
17754     
17755     setTitle : function(title, iconCls){
17756         this.title = title;
17757         if(this.header && this.headerAsText){
17758             this.header.child('span').update(title);
17759         }
17760         if(iconCls){
17761             this.setIconClass(iconCls);
17762         }
17763         this.fireEvent('titlechange', this, title);
17764         return this;
17765     },
17766
17767     
17768     getUpdater : function(){
17769         return this.body.getUpdater();
17770     },
17771
17772      
17773     load : function(){
17774         var um = this.body.getUpdater();
17775         um.update.apply(um, arguments);
17776         return this;
17777     },
17778
17779     
17780     beforeDestroy : function(){
17781         Ext.Panel.superclass.beforeDestroy.call(this);
17782         if(this.header){
17783             this.header.removeAllListeners();
17784         }
17785         if(this.tools){
17786             for(var k in this.tools){
17787                 Ext.destroy(this.tools[k]);
17788             }
17789         }
17790         if(this.toolbars.length > 0){
17791             Ext.each(this.toolbars, function(tb){
17792                 tb.un('afterlayout', this.syncHeight, this);
17793                 tb.un('remove', this.syncHeight, this);
17794             }, this);
17795         }
17796         if(Ext.isArray(this.buttons)){
17797             while(this.buttons.length) {
17798                 Ext.destroy(this.buttons[0]);
17799             }
17800         }
17801         if(this.rendered){
17802             Ext.destroy(
17803                 this.ft,
17804                 this.header,
17805                 this.footer,
17806                 this.tbar,
17807                 this.bbar,
17808                 this.body,
17809                 this.mc,
17810                 this.bwrap,
17811                 this.dd
17812             );
17813             if (this.fbar) {
17814                 Ext.destroy(
17815                     this.fbar,
17816                     this.fbar.el
17817                 );
17818             }
17819         }
17820         Ext.destroy(this.toolbars);
17821     },
17822
17823     
17824     createClasses : function(){
17825         this.headerCls = this.baseCls + '-header';
17826         this.headerTextCls = this.baseCls + '-header-text';
17827         this.bwrapCls = this.baseCls + '-bwrap';
17828         this.tbarCls = this.baseCls + '-tbar';
17829         this.bodyCls = this.baseCls + '-body';
17830         this.bbarCls = this.baseCls + '-bbar';
17831         this.footerCls = this.baseCls + '-footer';
17832     },
17833
17834     
17835     createGhost : function(cls, useShim, appendTo){
17836         var el = document.createElement('div');
17837         el.className = 'x-panel-ghost ' + (cls ? cls : '');
17838         if(this.header){
17839             el.appendChild(this.el.dom.firstChild.cloneNode(true));
17840         }
17841         Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
17842         el.style.width = this.el.dom.offsetWidth + 'px';;
17843         if(!appendTo){
17844             this.container.dom.appendChild(el);
17845         }else{
17846             Ext.getDom(appendTo).appendChild(el);
17847         }
17848         if(useShim !== false && this.el.useShim !== false){
17849             var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
17850             layer.show();
17851             return layer;
17852         }else{
17853             return new Ext.Element(el);
17854         }
17855     },
17856
17857     
17858     doAutoLoad : function(){
17859         var u = this.body.getUpdater();
17860         if(this.renderer){
17861             u.setRenderer(this.renderer);
17862         }
17863         u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {url: this.autoLoad});
17864     },
17865
17866     
17867     getTool : function(id) {
17868         return this.tools[id];
17869     }
17870
17871
17872 });
17873 Ext.reg('panel', Ext.Panel);
17874
17875 Ext.Editor = function(field, config){
17876     if(field.field){
17877         this.field = Ext.create(field.field, 'textfield');
17878         config = Ext.apply({}, field); 
17879         delete config.field;
17880     }else{
17881         this.field = field;
17882     }
17883     Ext.Editor.superclass.constructor.call(this, config);
17884 };
17885
17886 Ext.extend(Ext.Editor, Ext.Component, {
17887     
17888     
17889     allowBlur: true,
17890     
17891     
17892     
17893     
17894     
17895     value : "",
17896     
17897     alignment: "c-c?",
17898     
17899     offsets: [0, 0],
17900     
17901     shadow : "frame",
17902     
17903     constrain : false,
17904     
17905     swallowKeys : true,
17906     
17907     completeOnEnter : true,
17908     
17909     cancelOnEsc : true,
17910     
17911     updateEl : false,
17912
17913     initComponent : function(){
17914         Ext.Editor.superclass.initComponent.call(this);
17915         this.addEvents(
17916             
17917             "beforestartedit",
17918             
17919             "startedit",
17920             
17921             "beforecomplete",
17922             
17923             "complete",
17924             
17925             "canceledit",
17926             
17927             "specialkey"
17928         );
17929     },
17930
17931     
17932     onRender : function(ct, position){
17933         this.el = new Ext.Layer({
17934             shadow: this.shadow,
17935             cls: "x-editor",
17936             parentEl : ct,
17937             shim : this.shim,
17938             shadowOffset: this.shadowOffset || 4,
17939             id: this.id,
17940             constrain: this.constrain
17941         });
17942         if(this.zIndex){
17943             this.el.setZIndex(this.zIndex);
17944         }
17945         this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
17946         if(this.field.msgTarget != 'title'){
17947             this.field.msgTarget = 'qtip';
17948         }
17949         this.field.inEditor = true;
17950         this.mon(this.field, {
17951             scope: this,
17952             blur: this.onBlur,
17953             specialkey: this.onSpecialKey
17954         });
17955         if(this.field.grow){
17956             this.mon(this.field, "autosize", this.el.sync,  this.el, {delay:1});
17957         }
17958         this.field.render(this.el).show();
17959         this.field.getEl().dom.name = '';
17960         if(this.swallowKeys){
17961             this.field.el.swallowEvent([
17962                 'keypress', 
17963                 'keydown'   
17964             ]);
17965         }
17966     },
17967
17968     
17969     onSpecialKey : function(field, e){
17970         var key = e.getKey(),
17971             complete = this.completeOnEnter && key == e.ENTER,
17972             cancel = this.cancelOnEsc && key == e.ESC;
17973         if(complete || cancel){
17974             e.stopEvent();
17975             if(complete){
17976                 this.completeEdit();
17977             }else{
17978                 this.cancelEdit();
17979             }
17980             if(field.triggerBlur){
17981                 field.triggerBlur();
17982             }
17983         }
17984         this.fireEvent('specialkey', field, e);
17985     },
17986
17987     
17988     startEdit : function(el, value){
17989         if(this.editing){
17990             this.completeEdit();
17991         }
17992         this.boundEl = Ext.get(el);
17993         var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
17994         if(!this.rendered){
17995             this.render(this.parentEl || document.body);
17996         }
17997         if(this.fireEvent("beforestartedit", this, this.boundEl, v) !== false){
17998             this.startValue = v;
17999             this.field.reset();
18000             this.field.setValue(v);
18001             this.realign(true);
18002             this.editing = true;
18003             this.show();
18004         }
18005     },
18006
18007     
18008     doAutoSize : function(){
18009         if(this.autoSize){
18010             var sz = this.boundEl.getSize(),
18011                 fs = this.field.getSize();
18012
18013             switch(this.autoSize){
18014                 case "width":
18015                     this.setSize(sz.width, fs.height);
18016                     break;
18017                 case "height":
18018                     this.setSize(fs.width, sz.height);
18019                     break;
18020                 case "none":
18021                     this.setSize(fs.width, fs.height);
18022                     break;
18023                 default:
18024                     this.setSize(sz.width, sz.height);
18025             }
18026         }
18027     },
18028
18029     
18030     setSize : function(w, h){
18031         delete this.field.lastSize;
18032         this.field.setSize(w, h);
18033         if(this.el){
18034             
18035             if(Ext.isGecko2 || Ext.isOpera || (Ext.isIE7 && Ext.isStrict)){
18036                 
18037                 this.el.setSize(w, h);
18038             }
18039             this.el.sync();
18040         }
18041     },
18042
18043     
18044     realign : function(autoSize){
18045         if(autoSize === true){
18046             this.doAutoSize();
18047         }
18048         this.el.alignTo(this.boundEl, this.alignment, this.offsets);
18049     },
18050
18051     
18052     completeEdit : function(remainVisible){
18053         if(!this.editing){
18054             return;
18055         }
18056         
18057         if (this.field.assertValue) {
18058             this.field.assertValue();
18059         }
18060         var v = this.getValue();
18061         if(!this.field.isValid()){
18062             if(this.revertInvalid !== false){
18063                 this.cancelEdit(remainVisible);
18064             }
18065             return;
18066         }
18067         if(String(v) === String(this.startValue) && this.ignoreNoChange){
18068             this.hideEdit(remainVisible);
18069             return;
18070         }
18071         if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
18072             v = this.getValue();
18073             if(this.updateEl && this.boundEl){
18074                 this.boundEl.update(v);
18075             }
18076             this.hideEdit(remainVisible);
18077             this.fireEvent("complete", this, v, this.startValue);
18078         }
18079     },
18080
18081     
18082     onShow : function(){
18083         this.el.show();
18084         if(this.hideEl !== false){
18085             this.boundEl.hide();
18086         }
18087         this.field.show().focus(false, true);
18088         this.fireEvent("startedit", this.boundEl, this.startValue);
18089     },
18090
18091     
18092     cancelEdit : function(remainVisible){
18093         if(this.editing){
18094             var v = this.getValue();
18095             this.setValue(this.startValue);
18096             this.hideEdit(remainVisible);
18097             this.fireEvent("canceledit", this, v, this.startValue);
18098         }
18099     },
18100
18101     
18102     hideEdit: function(remainVisible){
18103         if(remainVisible !== true){
18104             this.editing = false;
18105             this.hide();
18106         }
18107     },
18108
18109     
18110     onBlur : function(){
18111         
18112         if(this.allowBlur === true && this.editing && this.selectSameEditor !== true){
18113             this.completeEdit();
18114         }
18115     },
18116
18117     
18118     onHide : function(){
18119         if(this.editing){
18120             this.completeEdit();
18121             return;
18122         }
18123         this.field.blur();
18124         if(this.field.collapse){
18125             this.field.collapse();
18126         }
18127         this.el.hide();
18128         if(this.hideEl !== false){
18129             this.boundEl.show();
18130         }
18131     },
18132
18133     
18134     setValue : function(v){
18135         this.field.setValue(v);
18136     },
18137
18138     
18139     getValue : function(){
18140         return this.field.getValue();
18141     },
18142
18143     beforeDestroy : function(){
18144         Ext.destroyMembers(this, 'field');
18145
18146         delete this.parentEl;
18147         delete this.boundEl;
18148     }
18149 });
18150 Ext.reg('editor', Ext.Editor);
18151
18152 Ext.ColorPalette = Ext.extend(Ext.Component, {
18153         
18154     
18155     itemCls : 'x-color-palette',
18156     
18157     value : null,
18158     
18159     clickEvent :'click',
18160     
18161     ctype : 'Ext.ColorPalette',
18162
18163     
18164     allowReselect : false,
18165
18166     
18167     colors : [
18168         '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
18169         '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
18170         'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
18171         'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
18172         'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
18173     ],
18174
18175     
18176     
18177     
18178     
18179     initComponent : function(){
18180         Ext.ColorPalette.superclass.initComponent.call(this);
18181         this.addEvents(
18182             
18183             'select'
18184         );
18185
18186         if(this.handler){
18187             this.on('select', this.handler, this.scope, true);
18188         }    
18189     },
18190
18191     
18192     onRender : function(container, position){
18193         this.autoEl = {
18194             tag: 'div',
18195             cls: this.itemCls
18196         };
18197         Ext.ColorPalette.superclass.onRender.call(this, container, position);
18198         var t = this.tpl || new Ext.XTemplate(
18199             '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'
18200         );
18201         t.overwrite(this.el, this.colors);
18202         this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'});
18203         if(this.clickEvent != 'click'){
18204                 this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true});
18205         }
18206     },
18207
18208     
18209     afterRender : function(){
18210         Ext.ColorPalette.superclass.afterRender.call(this);
18211         if(this.value){
18212             var s = this.value;
18213             this.value = null;
18214             this.select(s, true);
18215         }
18216     },
18217
18218     
18219     handleClick : function(e, t){
18220         e.preventDefault();
18221         if(!this.disabled){
18222             var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
18223             this.select(c.toUpperCase());
18224         }
18225     },
18226
18227     
18228     select : function(color, suppressEvent){
18229         color = color.replace('#', '');
18230         if(color != this.value || this.allowReselect){
18231             var el = this.el;
18232             if(this.value){
18233                 el.child('a.color-'+this.value).removeClass('x-color-palette-sel');
18234             }
18235             el.child('a.color-'+color).addClass('x-color-palette-sel');
18236             this.value = color;
18237             if(suppressEvent !== true){
18238                 this.fireEvent('select', this, color);
18239             }
18240         }
18241     }
18242
18243     
18244 });
18245 Ext.reg('colorpalette', Ext.ColorPalette);
18246 Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
18247     
18248     todayText : 'Today',
18249     
18250     okText : '&#160;OK&#160;',
18251     
18252     cancelText : 'Cancel',
18253     
18254     
18255     
18256     todayTip : '{0} (Spacebar)',
18257     
18258     minText : 'This date is before the minimum date',
18259     
18260     maxText : 'This date is after the maximum date',
18261     
18262     format : 'm/d/y',
18263     
18264     disabledDaysText : 'Disabled',
18265     
18266     disabledDatesText : 'Disabled',
18267     
18268     monthNames : Date.monthNames,
18269     
18270     dayNames : Date.dayNames,
18271     
18272     nextText : 'Next Month (Control+Right)',
18273     
18274     prevText : 'Previous Month (Control+Left)',
18275     
18276     monthYearText : 'Choose a month (Control+Up/Down to move years)',
18277     
18278     startDay : 0,
18279     
18280     showToday : true,
18281     
18282     
18283     
18284     
18285     
18286
18287     
18288     
18289     focusOnSelect: true,
18290
18291     
18292     
18293     initHour: 12, 
18294
18295     
18296     initComponent : function(){
18297         Ext.DatePicker.superclass.initComponent.call(this);
18298
18299         this.value = this.value ?
18300                  this.value.clearTime(true) : new Date().clearTime();
18301
18302         this.addEvents(
18303             
18304             'select'
18305         );
18306
18307         if(this.handler){
18308             this.on('select', this.handler,  this.scope || this);
18309         }
18310
18311         this.initDisabledDays();
18312     },
18313
18314     
18315     initDisabledDays : function(){
18316         if(!this.disabledDatesRE && this.disabledDates){
18317             var dd = this.disabledDates,
18318                 len = dd.length - 1,
18319                 re = '(?:';
18320
18321             Ext.each(dd, function(d, i){
18322                 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
18323                 if(i != len){
18324                     re += '|';
18325                 }
18326             }, this);
18327             this.disabledDatesRE = new RegExp(re + ')');
18328         }
18329     },
18330
18331     
18332     setDisabledDates : function(dd){
18333         if(Ext.isArray(dd)){
18334             this.disabledDates = dd;
18335             this.disabledDatesRE = null;
18336         }else{
18337             this.disabledDatesRE = dd;
18338         }
18339         this.initDisabledDays();
18340         this.update(this.value, true);
18341     },
18342
18343     
18344     setDisabledDays : function(dd){
18345         this.disabledDays = dd;
18346         this.update(this.value, true);
18347     },
18348
18349     
18350     setMinDate : function(dt){
18351         this.minDate = dt;
18352         this.update(this.value, true);
18353     },
18354
18355     
18356     setMaxDate : function(dt){
18357         this.maxDate = dt;
18358         this.update(this.value, true);
18359     },
18360
18361     
18362     setValue : function(value){
18363         this.value = value.clearTime(true);
18364         this.update(this.value);
18365     },
18366
18367     
18368     getValue : function(){
18369         return this.value;
18370     },
18371
18372     
18373     focus : function(){
18374         this.update(this.activeDate);
18375     },
18376
18377     
18378     onEnable: function(initial){
18379         Ext.DatePicker.superclass.onEnable.call(this);
18380         this.doDisabled(false);
18381         this.update(initial ? this.value : this.activeDate);
18382         if(Ext.isIE){
18383             this.el.repaint();
18384         }
18385
18386     },
18387
18388     
18389     onDisable : function(){
18390         Ext.DatePicker.superclass.onDisable.call(this);
18391         this.doDisabled(true);
18392         if(Ext.isIE && !Ext.isIE8){
18393             
18394              Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){
18395                  Ext.fly(el).repaint();
18396              });
18397         }
18398     },
18399
18400     
18401     doDisabled : function(disabled){
18402         this.keyNav.setDisabled(disabled);
18403         this.prevRepeater.setDisabled(disabled);
18404         this.nextRepeater.setDisabled(disabled);
18405         if(this.showToday){
18406             this.todayKeyListener.setDisabled(disabled);
18407             this.todayBtn.setDisabled(disabled);
18408         }
18409     },
18410
18411     
18412     onRender : function(container, position){
18413         var m = [
18414              '<table cellspacing="0">',
18415                 '<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'">&#160;</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'">&#160;</a></td></tr>',
18416                 '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
18417                 dn = this.dayNames,
18418                 i;
18419         for(i = 0; i < 7; i++){
18420             var d = this.startDay+i;
18421             if(d > 6){
18422                 d = d-7;
18423             }
18424             m.push('<th><span>', dn[d].substr(0,1), '</span></th>');
18425         }
18426         m[m.length] = '</tr></thead><tbody><tr>';
18427         for(i = 0; i < 42; i++) {
18428             if(i % 7 === 0 && i !== 0){
18429                 m[m.length] = '</tr><tr>';
18430             }
18431             m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
18432         }
18433         m.push('</tr></tbody></table></td></tr>',
18434                 this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
18435                 '</table><div class="x-date-mp"></div>');
18436
18437         var el = document.createElement('div');
18438         el.className = 'x-date-picker';
18439         el.innerHTML = m.join('');
18440
18441         container.dom.insertBefore(el, position);
18442
18443         this.el = Ext.get(el);
18444         this.eventEl = Ext.get(el.firstChild);
18445
18446         this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
18447             handler: this.showPrevMonth,
18448             scope: this,
18449             preventDefault:true,
18450             stopDefault:true
18451         });
18452
18453         this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
18454             handler: this.showNextMonth,
18455             scope: this,
18456             preventDefault:true,
18457             stopDefault:true
18458         });
18459
18460         this.monthPicker = this.el.down('div.x-date-mp');
18461         this.monthPicker.enableDisplayMode('block');
18462
18463         this.keyNav = new Ext.KeyNav(this.eventEl, {
18464             'left' : function(e){
18465                 if(e.ctrlKey){
18466                     this.showPrevMonth();
18467                 }else{
18468                     this.update(this.activeDate.add('d', -1));
18469                 }
18470             },
18471
18472             'right' : function(e){
18473                 if(e.ctrlKey){
18474                     this.showNextMonth();
18475                 }else{
18476                     this.update(this.activeDate.add('d', 1));
18477                 }
18478             },
18479
18480             'up' : function(e){
18481                 if(e.ctrlKey){
18482                     this.showNextYear();
18483                 }else{
18484                     this.update(this.activeDate.add('d', -7));
18485                 }
18486             },
18487
18488             'down' : function(e){
18489                 if(e.ctrlKey){
18490                     this.showPrevYear();
18491                 }else{
18492                     this.update(this.activeDate.add('d', 7));
18493                 }
18494             },
18495
18496             'pageUp' : function(e){
18497                 this.showNextMonth();
18498             },
18499
18500             'pageDown' : function(e){
18501                 this.showPrevMonth();
18502             },
18503
18504             'enter' : function(e){
18505                 e.stopPropagation();
18506                 return true;
18507             },
18508
18509             scope : this
18510         });
18511
18512         this.el.unselectable();
18513
18514         this.cells = this.el.select('table.x-date-inner tbody td');
18515         this.textNodes = this.el.query('table.x-date-inner tbody span');
18516
18517         this.mbtn = new Ext.Button({
18518             text: '&#160;',
18519             tooltip: this.monthYearText,
18520             renderTo: this.el.child('td.x-date-middle', true)
18521         });
18522         this.mbtn.el.child('em').addClass('x-btn-arrow');
18523
18524         if(this.showToday){
18525             this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);
18526             var today = (new Date()).dateFormat(this.format);
18527             this.todayBtn = new Ext.Button({
18528                 renderTo: this.el.child('td.x-date-bottom', true),
18529                 text: String.format(this.todayText, today),
18530                 tooltip: String.format(this.todayTip, today),
18531                 handler: this.selectToday,
18532                 scope: this
18533             });
18534         }
18535         this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
18536         this.mon(this.eventEl, 'click', this.handleDateClick,  this, {delegate: 'a.x-date-date'});
18537         this.mon(this.mbtn, 'click', this.showMonthPicker, this);
18538         this.onEnable(true);
18539     },
18540
18541     
18542     createMonthPicker : function(){
18543         if(!this.monthPicker.dom.firstChild){
18544             var buf = ['<table border="0" cellspacing="0">'];
18545             for(var i = 0; i < 6; i++){
18546                 buf.push(
18547                     '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',
18548                     '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',
18549                     i === 0 ?
18550                     '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' :
18551                     '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
18552                 );
18553             }
18554             buf.push(
18555                 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
18556                     this.okText,
18557                     '</button><button type="button" class="x-date-mp-cancel">',
18558                     this.cancelText,
18559                     '</button></td></tr>',
18560                 '</table>'
18561             );
18562             this.monthPicker.update(buf.join(''));
18563
18564             this.mon(this.monthPicker, 'click', this.onMonthClick, this);
18565             this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);
18566
18567             this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
18568             this.mpYears = this.monthPicker.select('td.x-date-mp-year');
18569
18570             this.mpMonths.each(function(m, a, i){
18571                 i += 1;
18572                 if((i%2) === 0){
18573                     m.dom.xmonth = 5 + Math.round(i * 0.5);
18574                 }else{
18575                     m.dom.xmonth = Math.round((i-1) * 0.5);
18576                 }
18577             });
18578         }
18579     },
18580
18581     
18582     showMonthPicker : function(){
18583         if(!this.disabled){
18584             this.createMonthPicker();
18585             var size = this.el.getSize();
18586             this.monthPicker.setSize(size);
18587             this.monthPicker.child('table').setSize(size);
18588
18589             this.mpSelMonth = (this.activeDate || this.value).getMonth();
18590             this.updateMPMonth(this.mpSelMonth);
18591             this.mpSelYear = (this.activeDate || this.value).getFullYear();
18592             this.updateMPYear(this.mpSelYear);
18593
18594             this.monthPicker.slideIn('t', {duration:0.2});
18595         }
18596     },
18597
18598     
18599     updateMPYear : function(y){
18600         this.mpyear = y;
18601         var ys = this.mpYears.elements;
18602         for(var i = 1; i <= 10; i++){
18603             var td = ys[i-1], y2;
18604             if((i%2) === 0){
18605                 y2 = y + Math.round(i * 0.5);
18606                 td.firstChild.innerHTML = y2;
18607                 td.xyear = y2;
18608             }else{
18609                 y2 = y - (5-Math.round(i * 0.5));
18610                 td.firstChild.innerHTML = y2;
18611                 td.xyear = y2;
18612             }
18613             this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
18614         }
18615     },
18616
18617     
18618     updateMPMonth : function(sm){
18619         this.mpMonths.each(function(m, a, i){
18620             m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
18621         });
18622     },
18623
18624     
18625     selectMPMonth : function(m){
18626
18627     },
18628
18629     
18630     onMonthClick : function(e, t){
18631         e.stopEvent();
18632         var el = new Ext.Element(t), pn;
18633         if(el.is('button.x-date-mp-cancel')){
18634             this.hideMonthPicker();
18635         }
18636         else if(el.is('button.x-date-mp-ok')){
18637             var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
18638             if(d.getMonth() != this.mpSelMonth){
18639                 
18640                 d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
18641             }
18642             this.update(d);
18643             this.hideMonthPicker();
18644         }
18645         else if((pn = el.up('td.x-date-mp-month', 2))){
18646             this.mpMonths.removeClass('x-date-mp-sel');
18647             pn.addClass('x-date-mp-sel');
18648             this.mpSelMonth = pn.dom.xmonth;
18649         }
18650         else if((pn = el.up('td.x-date-mp-year', 2))){
18651             this.mpYears.removeClass('x-date-mp-sel');
18652             pn.addClass('x-date-mp-sel');
18653             this.mpSelYear = pn.dom.xyear;
18654         }
18655         else if(el.is('a.x-date-mp-prev')){
18656             this.updateMPYear(this.mpyear-10);
18657         }
18658         else if(el.is('a.x-date-mp-next')){
18659             this.updateMPYear(this.mpyear+10);
18660         }
18661     },
18662
18663     
18664     onMonthDblClick : function(e, t){
18665         e.stopEvent();
18666         var el = new Ext.Element(t), pn;
18667         if((pn = el.up('td.x-date-mp-month', 2))){
18668             this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
18669             this.hideMonthPicker();
18670         }
18671         else if((pn = el.up('td.x-date-mp-year', 2))){
18672             this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
18673             this.hideMonthPicker();
18674         }
18675     },
18676
18677     
18678     hideMonthPicker : function(disableAnim){
18679         if(this.monthPicker){
18680             if(disableAnim === true){
18681                 this.monthPicker.hide();
18682             }else{
18683                 this.monthPicker.slideOut('t', {duration:0.2});
18684             }
18685         }
18686     },
18687
18688     
18689     showPrevMonth : function(e){
18690         this.update(this.activeDate.add('mo', -1));
18691     },
18692
18693     
18694     showNextMonth : function(e){
18695         this.update(this.activeDate.add('mo', 1));
18696     },
18697
18698     
18699     showPrevYear : function(){
18700         this.update(this.activeDate.add('y', -1));
18701     },
18702
18703     
18704     showNextYear : function(){
18705         this.update(this.activeDate.add('y', 1));
18706     },
18707
18708     
18709     handleMouseWheel : function(e){
18710         e.stopEvent();
18711         if(!this.disabled){
18712             var delta = e.getWheelDelta();
18713             if(delta > 0){
18714                 this.showPrevMonth();
18715             } else if(delta < 0){
18716                 this.showNextMonth();
18717             }
18718         }
18719     },
18720
18721     
18722     handleDateClick : function(e, t){
18723         e.stopEvent();
18724         if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
18725             this.cancelFocus = this.focusOnSelect === false;
18726             this.setValue(new Date(t.dateValue));
18727             delete this.cancelFocus;
18728             this.fireEvent('select', this, this.value);
18729         }
18730     },
18731
18732     
18733     selectToday : function(){
18734         if(this.todayBtn && !this.todayBtn.disabled){
18735             this.setValue(new Date().clearTime());
18736             this.fireEvent('select', this, this.value);
18737         }
18738     },
18739
18740     
18741     update : function(date, forceRefresh){
18742         if(this.rendered){
18743             var vd = this.activeDate, vis = this.isVisible();
18744             this.activeDate = date;
18745             if(!forceRefresh && vd && this.el){
18746                 var t = date.getTime();
18747                 if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
18748                     this.cells.removeClass('x-date-selected');
18749                     this.cells.each(function(c){
18750                        if(c.dom.firstChild.dateValue == t){
18751                            c.addClass('x-date-selected');
18752                            if(vis && !this.cancelFocus){
18753                                Ext.fly(c.dom.firstChild).focus(50);
18754                            }
18755                            return false;
18756                        }
18757                     }, this);
18758                     return;
18759                 }
18760             }
18761             var days = date.getDaysInMonth(),
18762                 firstOfMonth = date.getFirstDateOfMonth(),
18763                 startingPos = firstOfMonth.getDay()-this.startDay;
18764
18765             if(startingPos < 0){
18766                 startingPos += 7;
18767             }
18768             days += startingPos;
18769
18770             var pm = date.add('mo', -1),
18771                 prevStart = pm.getDaysInMonth()-startingPos,
18772                 cells = this.cells.elements,
18773                 textEls = this.textNodes,
18774                 
18775                 d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart, this.initHour)),
18776                 today = new Date().clearTime().getTime(),
18777                 sel = date.clearTime(true).getTime(),
18778                 min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
18779                 max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
18780                 ddMatch = this.disabledDatesRE,
18781                 ddText = this.disabledDatesText,
18782                 ddays = this.disabledDays ? this.disabledDays.join('') : false,
18783                 ddaysText = this.disabledDaysText,
18784                 format = this.format;
18785
18786             if(this.showToday){
18787                 var td = new Date().clearTime(),
18788                     disable = (td < min || td > max ||
18789                     (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
18790                     (ddays && ddays.indexOf(td.getDay()) != -1));
18791
18792                 if(!this.disabled){
18793                     this.todayBtn.setDisabled(disable);
18794                     this.todayKeyListener[disable ? 'disable' : 'enable']();
18795                 }
18796             }
18797
18798             var setCellClass = function(cal, cell){
18799                 cell.title = '';
18800                 var t = d.clearTime(true).getTime();
18801                 cell.firstChild.dateValue = t;
18802                 if(t == today){
18803                     cell.className += ' x-date-today';
18804                     cell.title = cal.todayText;
18805                 }
18806                 if(t == sel){
18807                     cell.className += ' x-date-selected';
18808                     if(vis){
18809                         Ext.fly(cell.firstChild).focus(50);
18810                     }
18811                 }
18812                 
18813                 if(t < min) {
18814                     cell.className = ' x-date-disabled';
18815                     cell.title = cal.minText;
18816                     return;
18817                 }
18818                 if(t > max) {
18819                     cell.className = ' x-date-disabled';
18820                     cell.title = cal.maxText;
18821                     return;
18822                 }
18823                 if(ddays){
18824                     if(ddays.indexOf(d.getDay()) != -1){
18825                         cell.title = ddaysText;
18826                         cell.className = ' x-date-disabled';
18827                     }
18828                 }
18829                 if(ddMatch && format){
18830                     var fvalue = d.dateFormat(format);
18831                     if(ddMatch.test(fvalue)){
18832                         cell.title = ddText.replace('%0', fvalue);
18833                         cell.className = ' x-date-disabled';
18834                     }
18835                 }
18836             };
18837
18838             var i = 0;
18839             for(; i < startingPos; i++) {
18840                 textEls[i].innerHTML = (++prevStart);
18841                 d.setDate(d.getDate()+1);
18842                 cells[i].className = 'x-date-prevday';
18843                 setCellClass(this, cells[i]);
18844             }
18845             for(; i < days; i++){
18846                 var intDay = i - startingPos + 1;
18847                 textEls[i].innerHTML = (intDay);
18848                 d.setDate(d.getDate()+1);
18849                 cells[i].className = 'x-date-active';
18850                 setCellClass(this, cells[i]);
18851             }
18852             var extraDays = 0;
18853             for(; i < 42; i++) {
18854                  textEls[i].innerHTML = (++extraDays);
18855                  d.setDate(d.getDate()+1);
18856                  cells[i].className = 'x-date-nextday';
18857                  setCellClass(this, cells[i]);
18858             }
18859
18860             this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
18861
18862             if(!this.internalRender){
18863                 var main = this.el.dom.firstChild,
18864                     w = main.offsetWidth;
18865                 this.el.setWidth(w + this.el.getBorderWidth('lr'));
18866                 Ext.fly(main).setWidth(w);
18867                 this.internalRender = true;
18868                 
18869                 
18870                 
18871                 if(Ext.isOpera && !this.secondPass){
18872                     main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
18873                     this.secondPass = true;
18874                     this.update.defer(10, this, [date]);
18875                 }
18876             }
18877         }
18878     },
18879
18880     
18881     beforeDestroy : function() {
18882         if(this.rendered){
18883             Ext.destroy(
18884                 this.keyNav,
18885                 this.monthPicker,
18886                 this.eventEl,
18887                 this.mbtn,
18888                 this.nextRepeater,
18889                 this.prevRepeater,
18890                 this.cells.el,
18891                 this.todayBtn
18892             );
18893             delete this.textNodes;
18894             delete this.cells.elements;
18895         }
18896     }
18897
18898     
18899 });
18900
18901 Ext.reg('datepicker', Ext.DatePicker);
18902
18903 Ext.LoadMask = function(el, config){
18904     this.el = Ext.get(el);
18905     Ext.apply(this, config);
18906     if(this.store){
18907         this.store.on({
18908             scope: this,
18909             beforeload: this.onBeforeLoad,
18910             load: this.onLoad,
18911             exception: this.onLoad
18912         });
18913         this.removeMask = Ext.value(this.removeMask, false);
18914     }else{
18915         var um = this.el.getUpdater();
18916         um.showLoadIndicator = false; 
18917         um.on({
18918             scope: this,
18919             beforeupdate: this.onBeforeLoad,
18920             update: this.onLoad,
18921             failure: this.onLoad
18922         });
18923         this.removeMask = Ext.value(this.removeMask, true);
18924     }
18925 };
18926
18927 Ext.LoadMask.prototype = {
18928     
18929     
18930     
18931     msg : 'Loading...',
18932     
18933     msgCls : 'x-mask-loading',
18934
18935     
18936     disabled: false,
18937
18938     
18939     disable : function(){
18940        this.disabled = true;
18941     },
18942
18943     
18944     enable : function(){
18945         this.disabled = false;
18946     },
18947
18948     
18949     onLoad : function(){
18950         this.el.unmask(this.removeMask);
18951     },
18952
18953     
18954     onBeforeLoad : function(){
18955         if(!this.disabled){
18956             this.el.mask(this.msg, this.msgCls);
18957         }
18958     },
18959
18960     
18961     show: function(){
18962         this.onBeforeLoad();
18963     },
18964
18965     
18966     hide: function(){
18967         this.onLoad();
18968     },
18969
18970     
18971     destroy : function(){
18972         if(this.store){
18973             this.store.un('beforeload', this.onBeforeLoad, this);
18974             this.store.un('load', this.onLoad, this);
18975             this.store.un('exception', this.onLoad, this);
18976         }else{
18977             var um = this.el.getUpdater();
18978             um.un('beforeupdate', this.onBeforeLoad, this);
18979             um.un('update', this.onLoad, this);
18980             um.un('failure', this.onLoad, this);
18981         }
18982     }
18983 };Ext.ns('Ext.slider');
18984
18985
18986 Ext.slider.Thumb = Ext.extend(Object, {
18987     
18988     
18989     dragging: false,
18990
18991     
18992     constructor: function(config) {
18993         
18994         Ext.apply(this, config || {}, {
18995             cls: 'x-slider-thumb',
18996
18997             
18998             constrain: false
18999         });
19000
19001         Ext.slider.Thumb.superclass.constructor.call(this, config);
19002
19003         if (this.slider.vertical) {
19004             Ext.apply(this, Ext.slider.Thumb.Vertical);
19005         }
19006     },
19007
19008     
19009     render: function() {
19010         this.el = this.slider.innerEl.insertFirst({cls: this.cls});
19011
19012         this.initEvents();
19013     },
19014
19015     
19016     enable: function() {
19017         this.disabled = false;
19018         this.el.removeClass(this.slider.disabledClass);
19019     },
19020
19021     
19022     disable: function() {
19023         this.disabled = true;
19024         this.el.addClass(this.slider.disabledClass);
19025     },
19026
19027     
19028     initEvents: function() {
19029         var el = this.el;
19030
19031         el.addClassOnOver('x-slider-thumb-over');
19032
19033         this.tracker = new Ext.dd.DragTracker({
19034             onBeforeStart: this.onBeforeDragStart.createDelegate(this),
19035             onStart      : this.onDragStart.createDelegate(this),
19036             onDrag       : this.onDrag.createDelegate(this),
19037             onEnd        : this.onDragEnd.createDelegate(this),
19038             tolerance    : 3,
19039             autoStart    : 300
19040         });
19041
19042         this.tracker.initEl(el);
19043     },
19044
19045     
19046     onBeforeDragStart : function(e) {
19047         if (this.disabled) {
19048             return false;
19049         } else {
19050             this.slider.promoteThumb(this);
19051             return true;
19052         }
19053     },
19054
19055     
19056     onDragStart: function(e){
19057         this.el.addClass('x-slider-thumb-drag');
19058         this.dragging = true;
19059         this.dragStartValue = this.value;
19060
19061         this.slider.fireEvent('dragstart', this.slider, e, this);
19062     },
19063
19064     
19065     onDrag: function(e) {
19066         var slider   = this.slider,
19067             index    = this.index,
19068             newValue = this.getNewValue();
19069
19070         if (this.constrain) {
19071             var above = slider.thumbs[index + 1],
19072                 below = slider.thumbs[index - 1];
19073
19074             if (below != undefined && newValue <= below.value) newValue = below.value;
19075             if (above != undefined && newValue >= above.value) newValue = above.value;
19076         }
19077
19078         slider.setValue(index, newValue, false);
19079         slider.fireEvent('drag', slider, e, this);
19080     },
19081
19082     getNewValue: function() {
19083         var slider   = this.slider,
19084             pos      = slider.innerEl.translatePoints(this.tracker.getXY());
19085
19086         return Ext.util.Format.round(slider.reverseValue(pos.left), slider.decimalPrecision);
19087     },
19088
19089     
19090     onDragEnd: function(e) {
19091         var slider = this.slider,
19092             value  = this.value;
19093
19094         this.el.removeClass('x-slider-thumb-drag');
19095
19096         this.dragging = false;
19097         slider.fireEvent('dragend', slider, e);
19098
19099         if (this.dragStartValue != value) {
19100             slider.fireEvent('changecomplete', slider, value, this);
19101         }
19102     },
19103     
19104     
19105     destroy: function(){
19106         Ext.destroyMembers(this, 'tracker', 'el');
19107     }
19108 });
19109
19110
19111 Ext.slider.MultiSlider = Ext.extend(Ext.BoxComponent, {
19112     
19113     
19114     vertical: false,
19115     
19116     minValue: 0,
19117     
19118     maxValue: 100,
19119     
19120     decimalPrecision: 0,
19121     
19122     keyIncrement: 1,
19123     
19124     increment: 0,
19125
19126     
19127     clickRange: [5,15],
19128
19129     
19130     clickToChange : true,
19131     
19132     animate: true,
19133     
19134     constrainThumbs: true,
19135
19136     
19137     topThumbZIndex: 10000,
19138
19139     
19140     initComponent : function(){
19141         if(!Ext.isDefined(this.value)){
19142             this.value = this.minValue;
19143         }
19144
19145         
19146         this.thumbs = [];
19147
19148         Ext.slider.MultiSlider.superclass.initComponent.call(this);
19149
19150         this.keyIncrement = Math.max(this.increment, this.keyIncrement);
19151         this.addEvents(
19152             
19153             'beforechange',
19154
19155             
19156             'change',
19157
19158             
19159             'changecomplete',
19160
19161             
19162             'dragstart',
19163
19164             
19165             'drag',
19166
19167             
19168             'dragend'
19169         );
19170
19171         
19172         if (this.values == undefined || Ext.isEmpty(this.values)) this.values = [0];
19173
19174         var values = this.values;
19175
19176         for (var i=0; i < values.length; i++) {
19177             this.addThumb(values[i]);
19178         }
19179
19180         if(this.vertical){
19181             Ext.apply(this, Ext.slider.Vertical);
19182         }
19183     },
19184
19185     
19186     addThumb: function(value) {
19187         var thumb = new Ext.slider.Thumb({
19188             value    : value,
19189             slider   : this,
19190             index    : this.thumbs.length,
19191             constrain: this.constrainThumbs
19192         });
19193         this.thumbs.push(thumb);
19194
19195         
19196         if (this.rendered) thumb.render();
19197     },
19198
19199     
19200     promoteThumb: function(topThumb) {
19201         var thumbs = this.thumbs,
19202             zIndex, thumb;
19203
19204         for (var i = 0, j = thumbs.length; i < j; i++) {
19205             thumb = thumbs[i];
19206
19207             if (thumb == topThumb) {
19208                 zIndex = this.topThumbZIndex;
19209             } else {
19210                 zIndex = '';
19211             }
19212
19213             thumb.el.setStyle('zIndex', zIndex);
19214         }
19215     },
19216
19217     
19218     onRender : function() {
19219         this.autoEl = {
19220             cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),
19221             cn : {
19222                 cls: 'x-slider-end',
19223                 cn : {
19224                     cls:'x-slider-inner',
19225                     cn : [{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]
19226                 }
19227             }
19228         };
19229
19230         Ext.slider.MultiSlider.superclass.onRender.apply(this, arguments);
19231
19232         this.endEl   = this.el.first();
19233         this.innerEl = this.endEl.first();
19234         this.focusEl = this.innerEl.child('.x-slider-focus');
19235
19236         
19237         for (var i=0; i < this.thumbs.length; i++) {
19238             this.thumbs[i].render();
19239         }
19240
19241         
19242         var thumb      = this.innerEl.child('.x-slider-thumb');
19243         this.halfThumb = (this.vertical ? thumb.getHeight() : thumb.getWidth()) / 2;
19244
19245         this.initEvents();
19246     },
19247
19248     
19249     initEvents : function(){
19250         this.mon(this.el, {
19251             scope    : this,
19252             mousedown: this.onMouseDown,
19253             keydown  : this.onKeyDown
19254         });
19255
19256         this.focusEl.swallowEvent("click", true);
19257     },
19258
19259     
19260     onMouseDown : function(e){
19261         if(this.disabled){
19262             return;
19263         }
19264
19265         
19266         var thumbClicked = false;
19267         for (var i=0; i < this.thumbs.length; i++) {
19268             thumbClicked = thumbClicked || e.target == this.thumbs[i].el.dom;
19269         }
19270
19271         if (this.clickToChange && !thumbClicked) {
19272             var local = this.innerEl.translatePoints(e.getXY());
19273             this.onClickChange(local);
19274         }
19275         this.focus();
19276     },
19277
19278     
19279     onClickChange : function(local) {
19280         if (local.top > this.clickRange[0] && local.top < this.clickRange[1]) {
19281             
19282             var thumb = this.getNearest(local, 'left'),
19283                 index = thumb.index;
19284
19285             this.setValue(index, Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);
19286         }
19287     },
19288
19289     
19290     getNearest: function(local, prop) {
19291         var localValue = prop == 'top' ? this.innerEl.getHeight() - local[prop] : local[prop],
19292             clickValue = this.reverseValue(localValue),
19293             nearestDistance = (this.maxValue - this.minValue) + 5, 
19294             index = 0,
19295             nearest = null;
19296
19297         for (var i=0; i < this.thumbs.length; i++) {
19298             var thumb = this.thumbs[i],
19299                 value = thumb.value,
19300                 dist  = Math.abs(value - clickValue);
19301
19302             if (Math.abs(dist <= nearestDistance)) {
19303                 nearest = thumb;
19304                 index = i;
19305                 nearestDistance = dist;
19306             }
19307         }
19308         return nearest;
19309     },
19310
19311     
19312     onKeyDown : function(e){
19313         
19314         if(this.disabled || this.thumbs.length !== 1){
19315             e.preventDefault();
19316             return;
19317         }
19318         var k = e.getKey(),
19319             val;
19320         switch(k){
19321             case e.UP:
19322             case e.RIGHT:
19323                 e.stopEvent();
19324                 val = e.ctrlKey ? this.maxValue : this.getValue(0) + this.keyIncrement;
19325                 this.setValue(0, val, undefined, true);
19326             break;
19327             case e.DOWN:
19328             case e.LEFT:
19329                 e.stopEvent();
19330                 val = e.ctrlKey ? this.minValue : this.getValue(0) - this.keyIncrement;
19331                 this.setValue(0, val, undefined, true);
19332             break;
19333             default:
19334                 e.preventDefault();
19335         }
19336     },
19337
19338     
19339     doSnap : function(value){
19340         if (!(this.increment && value)) {
19341             return value;
19342         }
19343         var newValue = value,
19344             inc = this.increment,
19345             m = value % inc;
19346         if (m != 0) {
19347             newValue -= m;
19348             if (m * 2 >= inc) {
19349                 newValue += inc;
19350             } else if (m * 2 < -inc) {
19351                 newValue -= inc;
19352             }
19353         }
19354         return newValue.constrain(this.minValue,  this.maxValue);
19355     },
19356
19357     
19358     afterRender : function(){
19359         Ext.slider.MultiSlider.superclass.afterRender.apply(this, arguments);
19360
19361         for (var i=0; i < this.thumbs.length; i++) {
19362             var thumb = this.thumbs[i];
19363
19364             if (thumb.value !== undefined) {
19365                 var v = this.normalizeValue(thumb.value);
19366
19367                 if (v !== thumb.value) {
19368                     
19369                     this.setValue(i, v, false);
19370                 } else {
19371                     this.moveThumb(i, this.translateValue(v), false);
19372                 }
19373             }
19374         };
19375     },
19376
19377     
19378     getRatio : function(){
19379         var w = this.innerEl.getWidth(),
19380             v = this.maxValue - this.minValue;
19381         return v == 0 ? w : (w/v);
19382     },
19383
19384     
19385     normalizeValue : function(v){
19386         v = this.doSnap(v);
19387         v = Ext.util.Format.round(v, this.decimalPrecision);
19388         v = v.constrain(this.minValue, this.maxValue);
19389         return v;
19390     },
19391
19392     
19393     setMinValue : function(val){
19394         this.minValue = val;
19395         var i = 0,
19396             thumbs = this.thumbs,
19397             len = thumbs.length,
19398             t;
19399             
19400         for(; i < len; ++i){
19401             t = thumbs[i];
19402             t.value = t.value < val ? val : t.value;
19403         }
19404         this.syncThumb();
19405     },
19406
19407     
19408     setMaxValue : function(val){
19409         this.maxValue = val;
19410         var i = 0,
19411             thumbs = this.thumbs,
19412             len = thumbs.length,
19413             t;
19414             
19415         for(; i < len; ++i){
19416             t = thumbs[i];
19417             t.value = t.value > val ? val : t.value;
19418         }
19419         this.syncThumb();
19420     },
19421
19422     
19423     setValue : function(index, v, animate, changeComplete) {
19424         var thumb = this.thumbs[index],
19425             el    = thumb.el;
19426
19427         v = this.normalizeValue(v);
19428
19429         if (v !== thumb.value && this.fireEvent('beforechange', this, v, thumb.value, thumb) !== false) {
19430             thumb.value = v;
19431             if(this.rendered){
19432                 this.moveThumb(index, this.translateValue(v), animate !== false);
19433                 this.fireEvent('change', this, v, thumb);
19434                 if(changeComplete){
19435                     this.fireEvent('changecomplete', this, v, thumb);
19436                 }
19437             }
19438         }
19439     },
19440
19441     
19442     translateValue : function(v) {
19443         var ratio = this.getRatio();
19444         return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
19445     },
19446
19447     
19448     reverseValue : function(pos){
19449         var ratio = this.getRatio();
19450         return (pos + (this.minValue * ratio)) / ratio;
19451     },
19452
19453     
19454     moveThumb: function(index, v, animate){
19455         var thumb = this.thumbs[index].el;
19456
19457         if(!animate || this.animate === false){
19458             thumb.setLeft(v);
19459         }else{
19460             thumb.shift({left: v, stopFx: true, duration:.35});
19461         }
19462     },
19463
19464     
19465     focus : function(){
19466         this.focusEl.focus(10);
19467     },
19468
19469     
19470     onResize : function(w, h){
19471         var thumbs = this.thumbs,
19472             len = thumbs.length,
19473             i = 0;
19474             
19475         
19476         for(; i < len; ++i){
19477             thumbs[i].el.stopFx();    
19478         }
19479         
19480         if(Ext.isNumber(w)){
19481             this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));
19482         }
19483         this.syncThumb();
19484         Ext.slider.MultiSlider.superclass.onResize.apply(this, arguments);
19485     },
19486
19487     
19488     onDisable: function(){
19489         Ext.slider.MultiSlider.superclass.onDisable.call(this);
19490
19491         for (var i=0; i < this.thumbs.length; i++) {
19492             var thumb = this.thumbs[i],
19493                 el    = thumb.el;
19494
19495             thumb.disable();
19496
19497             if(Ext.isIE){
19498                 
19499                 
19500                 var xy = el.getXY();
19501                 el.hide();
19502
19503                 this.innerEl.addClass(this.disabledClass).dom.disabled = true;
19504
19505                 if (!this.thumbHolder) {
19506                     this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});
19507                 }
19508
19509                 this.thumbHolder.show().setXY(xy);
19510             }
19511         }
19512     },
19513
19514     
19515     onEnable: function(){
19516         Ext.slider.MultiSlider.superclass.onEnable.call(this);
19517
19518         for (var i=0; i < this.thumbs.length; i++) {
19519             var thumb = this.thumbs[i],
19520                 el    = thumb.el;
19521
19522             thumb.enable();
19523
19524             if (Ext.isIE) {
19525                 this.innerEl.removeClass(this.disabledClass).dom.disabled = false;
19526
19527                 if (this.thumbHolder) this.thumbHolder.hide();
19528
19529                 el.show();
19530                 this.syncThumb();
19531             }
19532         }
19533     },
19534
19535     
19536     syncThumb : function() {
19537         if (this.rendered) {
19538             for (var i=0; i < this.thumbs.length; i++) {
19539                 this.moveThumb(i, this.translateValue(this.thumbs[i].value));
19540             }
19541         }
19542     },
19543
19544     
19545     getValue : function(index) {
19546         return this.thumbs[index].value;
19547     },
19548
19549     
19550     getValues: function() {
19551         var values = [];
19552
19553         for (var i=0; i < this.thumbs.length; i++) {
19554             values.push(this.thumbs[i].value);
19555         }
19556
19557         return values;
19558     },
19559
19560     
19561     beforeDestroy : function(){
19562         var thumbs = this.thumbs;
19563         for(var i = 0, len = thumbs.length; i < len; ++i){
19564             thumbs[i].destroy();
19565             thumbs[i] = null;
19566         }
19567         Ext.destroyMembers(this, 'endEl', 'innerEl', 'focusEl', 'thumbHolder');
19568         Ext.slider.MultiSlider.superclass.beforeDestroy.call(this);
19569     }
19570 });
19571
19572 Ext.reg('multislider', Ext.slider.MultiSlider);
19573
19574
19575 Ext.slider.SingleSlider = Ext.extend(Ext.slider.MultiSlider, {
19576     constructor: function(config) {
19577       config = config || {};
19578
19579       Ext.applyIf(config, {
19580           values: [config.value || 0]
19581       });
19582
19583       Ext.slider.SingleSlider.superclass.constructor.call(this, config);
19584     },
19585
19586     
19587     getValue: function() {
19588         
19589         return Ext.slider.SingleSlider.superclass.getValue.call(this, 0);
19590     },
19591
19592     
19593     setValue: function(value, animate) {
19594         var args = Ext.toArray(arguments),
19595             len  = args.length;
19596
19597         
19598         
19599         
19600         if (len == 1 || (len <= 3 && typeof arguments[1] != 'number')) {
19601             args.unshift(0);
19602         }
19603
19604         return Ext.slider.SingleSlider.superclass.setValue.apply(this, args);
19605     },
19606
19607     
19608     syncThumb : function() {
19609         return Ext.slider.SingleSlider.superclass.syncThumb.apply(this, [0].concat(arguments));
19610     },
19611     
19612     
19613     getNearest : function(){
19614         
19615         return this.thumbs[0];    
19616     }
19617 });
19618
19619
19620 Ext.Slider = Ext.slider.SingleSlider;
19621
19622 Ext.reg('slider', Ext.slider.SingleSlider);
19623
19624
19625 Ext.slider.Vertical = {
19626     onResize : function(w, h){
19627         this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));
19628         this.syncThumb();
19629     },
19630
19631     getRatio : function(){
19632         var h = this.innerEl.getHeight(),
19633             v = this.maxValue - this.minValue;
19634         return h/v;
19635     },
19636
19637     moveThumb: function(index, v, animate) {
19638         var thumb = this.thumbs[index],
19639             el    = thumb.el;
19640
19641         if (!animate || this.animate === false) {
19642             el.setBottom(v);
19643         } else {
19644             el.shift({bottom: v, stopFx: true, duration:.35});
19645         }
19646     },
19647
19648     onClickChange : function(local) {
19649         if (local.left > this.clickRange[0] && local.left < this.clickRange[1]) {
19650             var thumb = this.getNearest(local, 'top'),
19651                 index = thumb.index,
19652                 value = this.minValue + this.reverseValue(this.innerEl.getHeight() - local.top);
19653
19654             this.setValue(index, Ext.util.Format.round(value, this.decimalPrecision), undefined, true);
19655         }
19656     }
19657 };
19658
19659
19660 Ext.slider.Thumb.Vertical = {
19661     getNewValue: function() {
19662         var slider   = this.slider,
19663             innerEl  = slider.innerEl,
19664             pos      = innerEl.translatePoints(this.tracker.getXY()),
19665             bottom   = innerEl.getHeight() - pos.top;
19666
19667         return slider.minValue + Ext.util.Format.round(bottom / slider.getRatio(), slider.decimalPrecision);
19668     }
19669 };
19670
19671 Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
19672    
19673     baseCls : 'x-progress',
19674     
19675     
19676     animate : false,
19677
19678     
19679     waitTimer : null,
19680
19681     
19682     initComponent : function(){
19683         Ext.ProgressBar.superclass.initComponent.call(this);
19684         this.addEvents(
19685             
19686             "update"
19687         );
19688     },
19689
19690     
19691     onRender : function(ct, position){
19692         var tpl = new Ext.Template(
19693             '<div class="{cls}-wrap">',
19694                 '<div class="{cls}-inner">',
19695                     '<div class="{cls}-bar">',
19696                         '<div class="{cls}-text">',
19697                             '<div>&#160;</div>',
19698                         '</div>',
19699                     '</div>',
19700                     '<div class="{cls}-text {cls}-text-back">',
19701                         '<div>&#160;</div>',
19702                     '</div>',
19703                 '</div>',
19704             '</div>'
19705         );
19706
19707         this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)
19708             : tpl.append(ct, {cls: this.baseCls}, true);
19709                 
19710         if(this.id){
19711             this.el.dom.id = this.id;
19712         }
19713         var inner = this.el.dom.firstChild;
19714         this.progressBar = Ext.get(inner.firstChild);
19715
19716         if(this.textEl){
19717             
19718             this.textEl = Ext.get(this.textEl);
19719             delete this.textTopEl;
19720         }else{
19721             
19722             this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
19723             var textBackEl = Ext.get(inner.childNodes[1]);
19724             this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
19725             this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
19726             this.textEl.setWidth(inner.offsetWidth);
19727         }
19728         this.progressBar.setHeight(inner.offsetHeight);
19729     },
19730     
19731     
19732     afterRender : function(){
19733         Ext.ProgressBar.superclass.afterRender.call(this);
19734         if(this.value){
19735             this.updateProgress(this.value, this.text);
19736         }else{
19737             this.updateText(this.text);
19738         }
19739     },
19740
19741     
19742     updateProgress : function(value, text, animate){
19743         this.value = value || 0;
19744         if(text){
19745             this.updateText(text);
19746         }
19747         if(this.rendered && !this.isDestroyed){
19748             var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);
19749             this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));
19750             if(this.textTopEl){
19751                 
19752                 this.textTopEl.removeClass('x-hidden').setWidth(w);
19753             }
19754         }
19755         this.fireEvent('update', this, value, text);
19756         return this;
19757     },
19758
19759     
19760     wait : function(o){
19761         if(!this.waitTimer){
19762             var scope = this;
19763             o = o || {};
19764             this.updateText(o.text);
19765             this.waitTimer = Ext.TaskMgr.start({
19766                 run: function(i){
19767                     var inc = o.increment || 10;
19768                     i -= 1;
19769                     this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
19770                 },
19771                 interval: o.interval || 1000,
19772                 duration: o.duration,
19773                 onStop: function(){
19774                     if(o.fn){
19775                         o.fn.apply(o.scope || this);
19776                     }
19777                     this.reset();
19778                 },
19779                 scope: scope
19780             });
19781         }
19782         return this;
19783     },
19784
19785     
19786     isWaiting : function(){
19787         return this.waitTimer !== null;
19788     },
19789
19790     
19791     updateText : function(text){
19792         this.text = text || '&#160;';
19793         if(this.rendered){
19794             this.textEl.update(this.text);
19795         }
19796         return this;
19797     },
19798     
19799     
19800     syncProgressBar : function(){
19801         if(this.value){
19802             this.updateProgress(this.value, this.text);
19803         }
19804         return this;
19805     },
19806
19807     
19808     setSize : function(w, h){
19809         Ext.ProgressBar.superclass.setSize.call(this, w, h);
19810         if(this.textTopEl){
19811             var inner = this.el.dom.firstChild;
19812             this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
19813         }
19814         this.syncProgressBar();
19815         return this;
19816     },
19817
19818     
19819     reset : function(hide){
19820         this.updateProgress(0);
19821         if(this.textTopEl){
19822             this.textTopEl.addClass('x-hidden');
19823         }
19824         this.clearTimer();
19825         if(hide === true){
19826             this.hide();
19827         }
19828         return this;
19829     },
19830     
19831     
19832     clearTimer : function(){
19833         if(this.waitTimer){
19834             this.waitTimer.onStop = null; 
19835             Ext.TaskMgr.stop(this.waitTimer);
19836             this.waitTimer = null;
19837         }
19838     },
19839     
19840     onDestroy: function(){
19841         this.clearTimer();
19842         if(this.rendered){
19843             if(this.textEl.isComposite){
19844                 this.textEl.clear();
19845             }
19846             Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');
19847         }
19848         Ext.ProgressBar.superclass.onDestroy.call(this);
19849     }
19850 });
19851 Ext.reg('progress', Ext.ProgressBar);
19852
19853 (function() {
19854
19855 var Event=Ext.EventManager;
19856 var Dom=Ext.lib.Dom;
19857
19858
19859 Ext.dd.DragDrop = function(id, sGroup, config) {
19860     if(id) {
19861         this.init(id, sGroup, config);
19862     }
19863 };
19864
19865 Ext.dd.DragDrop.prototype = {
19866
19867     
19868
19869     
19870     id: null,
19871
19872     
19873     config: null,
19874
19875     
19876     dragElId: null,
19877
19878     
19879     handleElId: null,
19880
19881     
19882     invalidHandleTypes: null,
19883
19884     
19885     invalidHandleIds: null,
19886
19887     
19888     invalidHandleClasses: null,
19889
19890     
19891     startPageX: 0,
19892
19893     
19894     startPageY: 0,
19895
19896     
19897     groups: null,
19898
19899     
19900     locked: false,
19901
19902     
19903     lock: function() {
19904         this.locked = true;
19905     },
19906
19907     
19908     moveOnly: false,
19909
19910     
19911     unlock: function() {
19912         this.locked = false;
19913     },
19914
19915     
19916     isTarget: true,
19917
19918     
19919     padding: null,
19920
19921     
19922     _domRef: null,
19923
19924     
19925     __ygDragDrop: true,
19926
19927     
19928     constrainX: false,
19929
19930     
19931     constrainY: false,
19932
19933     
19934     minX: 0,
19935
19936     
19937     maxX: 0,
19938
19939     
19940     minY: 0,
19941
19942     
19943     maxY: 0,
19944
19945     
19946     maintainOffset: false,
19947
19948     
19949     xTicks: null,
19950
19951     
19952     yTicks: null,
19953
19954     
19955     primaryButtonOnly: true,
19956
19957     
19958     available: false,
19959
19960     
19961     hasOuterHandles: false,
19962
19963     
19964     b4StartDrag: function(x, y) { },
19965
19966     
19967     startDrag: function(x, y) {  },
19968
19969     
19970     b4Drag: function(e) { },
19971
19972     
19973     onDrag: function(e) {  },
19974
19975     
19976     onDragEnter: function(e, id) {  },
19977
19978     
19979     b4DragOver: function(e) { },
19980
19981     
19982     onDragOver: function(e, id) {  },
19983
19984     
19985     b4DragOut: function(e) { },
19986
19987     
19988     onDragOut: function(e, id) {  },
19989
19990     
19991     b4DragDrop: function(e) { },
19992
19993     
19994     onDragDrop: function(e, id) {  },
19995
19996     
19997     onInvalidDrop: function(e) {  },
19998
19999     
20000     b4EndDrag: function(e) { },
20001
20002     
20003     endDrag: function(e) {  },
20004
20005     
20006     b4MouseDown: function(e) {  },
20007
20008     
20009     onMouseDown: function(e) {  },
20010
20011     
20012     onMouseUp: function(e) {  },
20013
20014     
20015     onAvailable: function () {
20016     },
20017
20018     
20019     defaultPadding : {left:0, right:0, top:0, bottom:0},
20020
20021     
20022     constrainTo : function(constrainTo, pad, inContent){
20023         if(Ext.isNumber(pad)){
20024             pad = {left: pad, right:pad, top:pad, bottom:pad};
20025         }
20026         pad = pad || this.defaultPadding;
20027         var b = Ext.get(this.getEl()).getBox(),
20028             ce = Ext.get(constrainTo),
20029             s = ce.getScroll(),
20030             c, 
20031             cd = ce.dom;
20032         if(cd == document.body){
20033             c = { x: s.left, y: s.top, width: Ext.lib.Dom.getViewWidth(), height: Ext.lib.Dom.getViewHeight()};
20034         }else{
20035             var xy = ce.getXY();
20036             c = {x : xy[0], y: xy[1], width: cd.clientWidth, height: cd.clientHeight};
20037         }
20038
20039
20040         var topSpace = b.y - c.y,
20041             leftSpace = b.x - c.x;
20042
20043         this.resetConstraints();
20044         this.setXConstraint(leftSpace - (pad.left||0), 
20045                 c.width - leftSpace - b.width - (pad.right||0), 
20046                                 this.xTickSize
20047         );
20048         this.setYConstraint(topSpace - (pad.top||0), 
20049                 c.height - topSpace - b.height - (pad.bottom||0), 
20050                                 this.yTickSize
20051         );
20052     },
20053
20054     
20055     getEl: function() {
20056         if (!this._domRef) {
20057             this._domRef = Ext.getDom(this.id);
20058         }
20059
20060         return this._domRef;
20061     },
20062
20063     
20064     getDragEl: function() {
20065         return Ext.getDom(this.dragElId);
20066     },
20067
20068     
20069     init: function(id, sGroup, config) {
20070         this.initTarget(id, sGroup, config);
20071         Event.on(this.id, "mousedown", this.handleMouseDown, this);
20072         
20073     },
20074
20075     
20076     initTarget: function(id, sGroup, config) {
20077
20078         
20079         this.config = config || {};
20080
20081         
20082         this.DDM = Ext.dd.DDM;
20083         
20084         this.groups = {};
20085
20086         
20087         
20088         if (typeof id !== "string") {
20089             id = Ext.id(id);
20090         }
20091
20092         
20093         this.id = id;
20094
20095         
20096         this.addToGroup((sGroup) ? sGroup : "default");
20097
20098         
20099         
20100         this.handleElId = id;
20101
20102         
20103         this.setDragElId(id);
20104
20105         
20106         this.invalidHandleTypes = { A: "A" };
20107         this.invalidHandleIds = {};
20108         this.invalidHandleClasses = [];
20109
20110         this.applyConfig();
20111
20112         this.handleOnAvailable();
20113     },
20114
20115     
20116     applyConfig: function() {
20117
20118         
20119         
20120         this.padding           = this.config.padding || [0, 0, 0, 0];
20121         this.isTarget          = (this.config.isTarget !== false);
20122         this.maintainOffset    = (this.config.maintainOffset);
20123         this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
20124
20125     },
20126
20127     
20128     handleOnAvailable: function() {
20129         this.available = true;
20130         this.resetConstraints();
20131         this.onAvailable();
20132     },
20133
20134      
20135     setPadding: function(iTop, iRight, iBot, iLeft) {
20136         
20137         if (!iRight && 0 !== iRight) {
20138             this.padding = [iTop, iTop, iTop, iTop];
20139         } else if (!iBot && 0 !== iBot) {
20140             this.padding = [iTop, iRight, iTop, iRight];
20141         } else {
20142             this.padding = [iTop, iRight, iBot, iLeft];
20143         }
20144     },
20145
20146     
20147     setInitPosition: function(diffX, diffY) {
20148         var el = this.getEl();
20149
20150         if (!this.DDM.verifyEl(el)) {
20151             return;
20152         }
20153
20154         var dx = diffX || 0;
20155         var dy = diffY || 0;
20156
20157         var p = Dom.getXY( el );
20158
20159         this.initPageX = p[0] - dx;
20160         this.initPageY = p[1] - dy;
20161
20162         this.lastPageX = p[0];
20163         this.lastPageY = p[1];
20164
20165         this.setStartPosition(p);
20166     },
20167
20168     
20169     setStartPosition: function(pos) {
20170         var p = pos || Dom.getXY( this.getEl() );
20171         this.deltaSetXY = null;
20172
20173         this.startPageX = p[0];
20174         this.startPageY = p[1];
20175     },
20176
20177     
20178     addToGroup: function(sGroup) {
20179         this.groups[sGroup] = true;
20180         this.DDM.regDragDrop(this, sGroup);
20181     },
20182
20183     
20184     removeFromGroup: function(sGroup) {
20185         if (this.groups[sGroup]) {
20186             delete this.groups[sGroup];
20187         }
20188
20189         this.DDM.removeDDFromGroup(this, sGroup);
20190     },
20191
20192     
20193     setDragElId: function(id) {
20194         this.dragElId = id;
20195     },
20196
20197     
20198     setHandleElId: function(id) {
20199         if (typeof id !== "string") {
20200             id = Ext.id(id);
20201         }
20202         this.handleElId = id;
20203         this.DDM.regHandle(this.id, id);
20204     },
20205
20206     
20207     setOuterHandleElId: function(id) {
20208         if (typeof id !== "string") {
20209             id = Ext.id(id);
20210         }
20211         Event.on(id, "mousedown",
20212                 this.handleMouseDown, this);
20213         this.setHandleElId(id);
20214
20215         this.hasOuterHandles = true;
20216     },
20217
20218     
20219     unreg: function() {
20220         Event.un(this.id, "mousedown",
20221                 this.handleMouseDown);
20222         this._domRef = null;
20223         this.DDM._remove(this);
20224     },
20225
20226     destroy : function(){
20227         this.unreg();
20228     },
20229
20230     
20231     isLocked: function() {
20232         return (this.DDM.isLocked() || this.locked);
20233     },
20234
20235     
20236     handleMouseDown: function(e, oDD){
20237         if (this.primaryButtonOnly && e.button != 0) {
20238             return;
20239         }
20240
20241         if (this.isLocked()) {
20242             return;
20243         }
20244
20245         this.DDM.refreshCache(this.groups);
20246
20247         var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e));
20248         if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) )  {
20249         } else {
20250             if (this.clickValidator(e)) {
20251
20252                 
20253                 this.setStartPosition();
20254
20255                 this.b4MouseDown(e);
20256                 this.onMouseDown(e);
20257
20258                 this.DDM.handleMouseDown(e, this);
20259
20260                 this.DDM.stopEvent(e);
20261             } else {
20262
20263
20264             }
20265         }
20266     },
20267
20268     clickValidator: function(e) {
20269         var target = e.getTarget();
20270         return ( this.isValidHandleChild(target) &&
20271                     (this.id == this.handleElId ||
20272                         this.DDM.handleWasClicked(target, this.id)) );
20273     },
20274
20275     
20276     addInvalidHandleType: function(tagName) {
20277         var type = tagName.toUpperCase();
20278         this.invalidHandleTypes[type] = type;
20279     },
20280
20281     
20282     addInvalidHandleId: function(id) {
20283         if (typeof id !== "string") {
20284             id = Ext.id(id);
20285         }
20286         this.invalidHandleIds[id] = id;
20287     },
20288
20289     
20290     addInvalidHandleClass: function(cssClass) {
20291         this.invalidHandleClasses.push(cssClass);
20292     },
20293
20294     
20295     removeInvalidHandleType: function(tagName) {
20296         var type = tagName.toUpperCase();
20297         
20298         delete this.invalidHandleTypes[type];
20299     },
20300
20301     
20302     removeInvalidHandleId: function(id) {
20303         if (typeof id !== "string") {
20304             id = Ext.id(id);
20305         }
20306         delete this.invalidHandleIds[id];
20307     },
20308
20309     
20310     removeInvalidHandleClass: function(cssClass) {
20311         for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
20312             if (this.invalidHandleClasses[i] == cssClass) {
20313                 delete this.invalidHandleClasses[i];
20314             }
20315         }
20316     },
20317
20318     
20319     isValidHandleChild: function(node) {
20320
20321         var valid = true;
20322         
20323         var nodeName;
20324         try {
20325             nodeName = node.nodeName.toUpperCase();
20326         } catch(e) {
20327             nodeName = node.nodeName;
20328         }
20329         valid = valid && !this.invalidHandleTypes[nodeName];
20330         valid = valid && !this.invalidHandleIds[node.id];
20331
20332         for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
20333             valid = !Ext.fly(node).hasClass(this.invalidHandleClasses[i]);
20334         }
20335
20336
20337         return valid;
20338
20339     },
20340
20341     
20342     setXTicks: function(iStartX, iTickSize) {
20343         this.xTicks = [];
20344         this.xTickSize = iTickSize;
20345
20346         var tickMap = {};
20347
20348         for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
20349             if (!tickMap[i]) {
20350                 this.xTicks[this.xTicks.length] = i;
20351                 tickMap[i] = true;
20352             }
20353         }
20354
20355         for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
20356             if (!tickMap[i]) {
20357                 this.xTicks[this.xTicks.length] = i;
20358                 tickMap[i] = true;
20359             }
20360         }
20361
20362         this.xTicks.sort(this.DDM.numericSort) ;
20363     },
20364
20365     
20366     setYTicks: function(iStartY, iTickSize) {
20367         this.yTicks = [];
20368         this.yTickSize = iTickSize;
20369
20370         var tickMap = {};
20371
20372         for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
20373             if (!tickMap[i]) {
20374                 this.yTicks[this.yTicks.length] = i;
20375                 tickMap[i] = true;
20376             }
20377         }
20378
20379         for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
20380             if (!tickMap[i]) {
20381                 this.yTicks[this.yTicks.length] = i;
20382                 tickMap[i] = true;
20383             }
20384         }
20385
20386         this.yTicks.sort(this.DDM.numericSort) ;
20387     },
20388
20389     
20390     setXConstraint: function(iLeft, iRight, iTickSize) {
20391         this.leftConstraint = iLeft;
20392         this.rightConstraint = iRight;
20393
20394         this.minX = this.initPageX - iLeft;
20395         this.maxX = this.initPageX + iRight;
20396         if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
20397
20398         this.constrainX = true;
20399     },
20400
20401     
20402     clearConstraints: function() {
20403         this.constrainX = false;
20404         this.constrainY = false;
20405         this.clearTicks();
20406     },
20407
20408     
20409     clearTicks: function() {
20410         this.xTicks = null;
20411         this.yTicks = null;
20412         this.xTickSize = 0;
20413         this.yTickSize = 0;
20414     },
20415
20416     
20417     setYConstraint: function(iUp, iDown, iTickSize) {
20418         this.topConstraint = iUp;
20419         this.bottomConstraint = iDown;
20420
20421         this.minY = this.initPageY - iUp;
20422         this.maxY = this.initPageY + iDown;
20423         if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
20424
20425         this.constrainY = true;
20426
20427     },
20428
20429     
20430     resetConstraints: function() {
20431         
20432         if (this.initPageX || this.initPageX === 0) {
20433             
20434             var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
20435             var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
20436
20437             this.setInitPosition(dx, dy);
20438
20439         
20440         } else {
20441             this.setInitPosition();
20442         }
20443
20444         if (this.constrainX) {
20445             this.setXConstraint( this.leftConstraint,
20446                                  this.rightConstraint,
20447                                  this.xTickSize        );
20448         }
20449
20450         if (this.constrainY) {
20451             this.setYConstraint( this.topConstraint,
20452                                  this.bottomConstraint,
20453                                  this.yTickSize         );
20454         }
20455     },
20456
20457     
20458     getTick: function(val, tickArray) {
20459         if (!tickArray) {
20460             
20461             
20462             return val;
20463         } else if (tickArray[0] >= val) {
20464             
20465             
20466             return tickArray[0];
20467         } else {
20468             for (var i=0, len=tickArray.length; i<len; ++i) {
20469                 var next = i + 1;
20470                 if (tickArray[next] && tickArray[next] >= val) {
20471                     var diff1 = val - tickArray[i];
20472                     var diff2 = tickArray[next] - val;
20473                     return (diff2 > diff1) ? tickArray[i] : tickArray[next];
20474                 }
20475             }
20476
20477             
20478             
20479             return tickArray[tickArray.length - 1];
20480         }
20481     },
20482
20483     
20484     toString: function() {
20485         return ("DragDrop " + this.id);
20486     }
20487
20488 };
20489
20490 })();
20491
20492
20493
20494
20495 if (!Ext.dd.DragDropMgr) {
20496
20497
20498 Ext.dd.DragDropMgr = function() {
20499
20500     var Event = Ext.EventManager;
20501
20502     return {
20503
20504         
20505         ids: {},
20506
20507         
20508         handleIds: {},
20509
20510         
20511         dragCurrent: null,
20512
20513         
20514         dragOvers: {},
20515
20516         
20517         deltaX: 0,
20518
20519         
20520         deltaY: 0,
20521
20522         
20523         preventDefault: true,
20524
20525         
20526         stopPropagation: true,
20527
20528         
20529         initialized: false,
20530
20531         
20532         locked: false,
20533
20534         
20535         init: function() {
20536             this.initialized = true;
20537         },
20538
20539         
20540         POINT: 0,
20541
20542         
20543         INTERSECT: 1,
20544
20545         
20546         mode: 0,
20547
20548         
20549         _execOnAll: function(sMethod, args) {
20550             for (var i in this.ids) {
20551                 for (var j in this.ids[i]) {
20552                     var oDD = this.ids[i][j];
20553                     if (! this.isTypeOfDD(oDD)) {
20554                         continue;
20555                     }
20556                     oDD[sMethod].apply(oDD, args);
20557                 }
20558             }
20559         },
20560
20561         
20562         _onLoad: function() {
20563
20564             this.init();
20565
20566
20567             Event.on(document, "mouseup",   this.handleMouseUp, this, true);
20568             Event.on(document, "mousemove", this.handleMouseMove, this, true);
20569             Event.on(window,   "unload",    this._onUnload, this, true);
20570             Event.on(window,   "resize",    this._onResize, this, true);
20571             
20572
20573         },
20574
20575         
20576         _onResize: function(e) {
20577             this._execOnAll("resetConstraints", []);
20578         },
20579
20580         
20581         lock: function() { this.locked = true; },
20582
20583         
20584         unlock: function() { this.locked = false; },
20585
20586         
20587         isLocked: function() { return this.locked; },
20588
20589         
20590         locationCache: {},
20591
20592         
20593         useCache: true,
20594
20595         
20596         clickPixelThresh: 3,
20597
20598         
20599         clickTimeThresh: 350,
20600
20601         
20602         dragThreshMet: false,
20603
20604         
20605         clickTimeout: null,
20606
20607         
20608         startX: 0,
20609
20610         
20611         startY: 0,
20612
20613         
20614         regDragDrop: function(oDD, sGroup) {
20615             if (!this.initialized) { this.init(); }
20616
20617             if (!this.ids[sGroup]) {
20618                 this.ids[sGroup] = {};
20619             }
20620             this.ids[sGroup][oDD.id] = oDD;
20621         },
20622
20623         
20624         removeDDFromGroup: function(oDD, sGroup) {
20625             if (!this.ids[sGroup]) {
20626                 this.ids[sGroup] = {};
20627             }
20628
20629             var obj = this.ids[sGroup];
20630             if (obj && obj[oDD.id]) {
20631                 delete obj[oDD.id];
20632             }
20633         },
20634
20635         
20636         _remove: function(oDD) {
20637             for (var g in oDD.groups) {
20638                 if (g && this.ids[g] && this.ids[g][oDD.id]) {
20639                     delete this.ids[g][oDD.id];
20640                 }
20641             }
20642             delete this.handleIds[oDD.id];
20643         },
20644
20645         
20646         regHandle: function(sDDId, sHandleId) {
20647             if (!this.handleIds[sDDId]) {
20648                 this.handleIds[sDDId] = {};
20649             }
20650             this.handleIds[sDDId][sHandleId] = sHandleId;
20651         },
20652
20653         
20654         isDragDrop: function(id) {
20655             return ( this.getDDById(id) ) ? true : false;
20656         },
20657
20658         
20659         getRelated: function(p_oDD, bTargetsOnly) {
20660             var oDDs = [];
20661             for (var i in p_oDD.groups) {
20662                 for (var j in this.ids[i]) {
20663                     var dd = this.ids[i][j];
20664                     if (! this.isTypeOfDD(dd)) {
20665                         continue;
20666                     }
20667                     if (!bTargetsOnly || dd.isTarget) {
20668                         oDDs[oDDs.length] = dd;
20669                     }
20670                 }
20671             }
20672
20673             return oDDs;
20674         },
20675
20676         
20677         isLegalTarget: function (oDD, oTargetDD) {
20678             var targets = this.getRelated(oDD, true);
20679             for (var i=0, len=targets.length;i<len;++i) {
20680                 if (targets[i].id == oTargetDD.id) {
20681                     return true;
20682                 }
20683             }
20684
20685             return false;
20686         },
20687
20688         
20689         isTypeOfDD: function (oDD) {
20690             return (oDD && oDD.__ygDragDrop);
20691         },
20692
20693         
20694         isHandle: function(sDDId, sHandleId) {
20695             return ( this.handleIds[sDDId] &&
20696                             this.handleIds[sDDId][sHandleId] );
20697         },
20698
20699         
20700         getDDById: function(id) {
20701             for (var i in this.ids) {
20702                 if (this.ids[i][id]) {
20703                     return this.ids[i][id];
20704                 }
20705             }
20706             return null;
20707         },
20708
20709         
20710         handleMouseDown: function(e, oDD) {
20711             if(Ext.QuickTips){
20712                 Ext.QuickTips.ddDisable();
20713             }
20714             if(this.dragCurrent){
20715                 
20716                 
20717                 this.handleMouseUp(e);
20718             }
20719             
20720             this.currentTarget = e.getTarget();
20721             this.dragCurrent = oDD;
20722
20723             var el = oDD.getEl();
20724
20725             
20726             this.startX = e.getPageX();
20727             this.startY = e.getPageY();
20728
20729             this.deltaX = this.startX - el.offsetLeft;
20730             this.deltaY = this.startY - el.offsetTop;
20731
20732             this.dragThreshMet = false;
20733
20734             this.clickTimeout = setTimeout(
20735                     function() {
20736                         var DDM = Ext.dd.DDM;
20737                         DDM.startDrag(DDM.startX, DDM.startY);
20738                     },
20739                     this.clickTimeThresh );
20740         },
20741
20742         
20743         startDrag: function(x, y) {
20744             clearTimeout(this.clickTimeout);
20745             if (this.dragCurrent) {
20746                 this.dragCurrent.b4StartDrag(x, y);
20747                 this.dragCurrent.startDrag(x, y);
20748             }
20749             this.dragThreshMet = true;
20750         },
20751
20752         
20753         handleMouseUp: function(e) {
20754
20755             if(Ext.QuickTips){
20756                 Ext.QuickTips.ddEnable();
20757             }
20758             if (! this.dragCurrent) {
20759                 return;
20760             }
20761
20762             clearTimeout(this.clickTimeout);
20763
20764             if (this.dragThreshMet) {
20765                 this.fireEvents(e, true);
20766             } else {
20767             }
20768
20769             this.stopDrag(e);
20770
20771             this.stopEvent(e);
20772         },
20773
20774         
20775         stopEvent: function(e){
20776             if(this.stopPropagation) {
20777                 e.stopPropagation();
20778             }
20779
20780             if (this.preventDefault) {
20781                 e.preventDefault();
20782             }
20783         },
20784
20785         
20786         stopDrag: function(e) {
20787             
20788             if (this.dragCurrent) {
20789                 if (this.dragThreshMet) {
20790                     this.dragCurrent.b4EndDrag(e);
20791                     this.dragCurrent.endDrag(e);
20792                 }
20793
20794                 this.dragCurrent.onMouseUp(e);
20795             }
20796
20797             this.dragCurrent = null;
20798             this.dragOvers = {};
20799         },
20800
20801         
20802         handleMouseMove: function(e) {
20803             if (! this.dragCurrent) {
20804                 return true;
20805             }
20806             
20807
20808             
20809             if (Ext.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
20810                 this.stopEvent(e);
20811                 return this.handleMouseUp(e);
20812             }
20813
20814             if (!this.dragThreshMet) {
20815                 var diffX = Math.abs(this.startX - e.getPageX());
20816                 var diffY = Math.abs(this.startY - e.getPageY());
20817                 if (diffX > this.clickPixelThresh ||
20818                             diffY > this.clickPixelThresh) {
20819                     this.startDrag(this.startX, this.startY);
20820                 }
20821             }
20822
20823             if (this.dragThreshMet) {
20824                 this.dragCurrent.b4Drag(e);
20825                 this.dragCurrent.onDrag(e);
20826                 if(!this.dragCurrent.moveOnly){
20827                     this.fireEvents(e, false);
20828                 }
20829             }
20830
20831             this.stopEvent(e);
20832
20833             return true;
20834         },
20835
20836         
20837         fireEvents: function(e, isDrop) {
20838             var dc = this.dragCurrent;
20839
20840             
20841             
20842             if (!dc || dc.isLocked()) {
20843                 return;
20844             }
20845
20846             var pt = e.getPoint();
20847
20848             
20849             var oldOvers = [];
20850
20851             var outEvts   = [];
20852             var overEvts  = [];
20853             var dropEvts  = [];
20854             var enterEvts = [];
20855
20856             
20857             
20858             for (var i in this.dragOvers) {
20859
20860                 var ddo = this.dragOvers[i];
20861
20862                 if (! this.isTypeOfDD(ddo)) {
20863                     continue;
20864                 }
20865
20866                 if (! this.isOverTarget(pt, ddo, this.mode)) {
20867                     outEvts.push( ddo );
20868                 }
20869
20870                 oldOvers[i] = true;
20871                 delete this.dragOvers[i];
20872             }
20873
20874             for (var sGroup in dc.groups) {
20875
20876                 if ("string" != typeof sGroup) {
20877                     continue;
20878                 }
20879
20880                 for (i in this.ids[sGroup]) {
20881                     var oDD = this.ids[sGroup][i];
20882                     if (! this.isTypeOfDD(oDD)) {
20883                         continue;
20884                     }
20885
20886                     if (oDD.isTarget && !oDD.isLocked() && ((oDD != dc) || (dc.ignoreSelf === false))) {
20887                         if (this.isOverTarget(pt, oDD, this.mode)) {
20888                             
20889                             if (isDrop) {
20890                                 dropEvts.push( oDD );
20891                             
20892                             } else {
20893
20894                                 
20895                                 if (!oldOvers[oDD.id]) {
20896                                     enterEvts.push( oDD );
20897                                 
20898                                 } else {
20899                                     overEvts.push( oDD );
20900                                 }
20901
20902                                 this.dragOvers[oDD.id] = oDD;
20903                             }
20904                         }
20905                     }
20906                 }
20907             }
20908
20909             if (this.mode) {
20910                 if (outEvts.length) {
20911                     dc.b4DragOut(e, outEvts);
20912                     dc.onDragOut(e, outEvts);
20913                 }
20914
20915                 if (enterEvts.length) {
20916                     dc.onDragEnter(e, enterEvts);
20917                 }
20918
20919                 if (overEvts.length) {
20920                     dc.b4DragOver(e, overEvts);
20921                     dc.onDragOver(e, overEvts);
20922                 }
20923
20924                 if (dropEvts.length) {
20925                     dc.b4DragDrop(e, dropEvts);
20926                     dc.onDragDrop(e, dropEvts);
20927                 }
20928
20929             } else {
20930                 
20931                 var len = 0;
20932                 for (i=0, len=outEvts.length; i<len; ++i) {
20933                     dc.b4DragOut(e, outEvts[i].id);
20934                     dc.onDragOut(e, outEvts[i].id);
20935                 }
20936
20937                 
20938                 for (i=0,len=enterEvts.length; i<len; ++i) {
20939                     
20940                     dc.onDragEnter(e, enterEvts[i].id);
20941                 }
20942
20943                 
20944                 for (i=0,len=overEvts.length; i<len; ++i) {
20945                     dc.b4DragOver(e, overEvts[i].id);
20946                     dc.onDragOver(e, overEvts[i].id);
20947                 }
20948
20949                 
20950                 for (i=0, len=dropEvts.length; i<len; ++i) {
20951                     dc.b4DragDrop(e, dropEvts[i].id);
20952                     dc.onDragDrop(e, dropEvts[i].id);
20953                 }
20954
20955             }
20956
20957             
20958             if (isDrop && !dropEvts.length) {
20959                 dc.onInvalidDrop(e);
20960             }
20961
20962         },
20963
20964         
20965         getBestMatch: function(dds) {
20966             var winner = null;
20967             
20968             
20969                
20970             
20971             
20972
20973             var len = dds.length;
20974
20975             if (len == 1) {
20976                 winner = dds[0];
20977             } else {
20978                 
20979                 for (var i=0; i<len; ++i) {
20980                     var dd = dds[i];
20981                     
20982                     
20983                     
20984                     if (dd.cursorIsOver) {
20985                         winner = dd;
20986                         break;
20987                     
20988                     } else {
20989                         if (!winner ||
20990                             winner.overlap.getArea() < dd.overlap.getArea()) {
20991                             winner = dd;
20992                         }
20993                     }
20994                 }
20995             }
20996
20997             return winner;
20998         },
20999
21000         
21001         refreshCache: function(groups) {
21002             for (var sGroup in groups) {
21003                 if ("string" != typeof sGroup) {
21004                     continue;
21005                 }
21006                 for (var i in this.ids[sGroup]) {
21007                     var oDD = this.ids[sGroup][i];
21008
21009                     if (this.isTypeOfDD(oDD)) {
21010                     
21011                         var loc = this.getLocation(oDD);
21012                         if (loc) {
21013                             this.locationCache[oDD.id] = loc;
21014                         } else {
21015                             delete this.locationCache[oDD.id];
21016                             
21017                             
21018                             
21019                         }
21020                     }
21021                 }
21022             }
21023         },
21024
21025         
21026         verifyEl: function(el) {
21027             if (el) {
21028                 var parent;
21029                 if(Ext.isIE){
21030                     try{
21031                         parent = el.offsetParent;
21032                     }catch(e){}
21033                 }else{
21034                     parent = el.offsetParent;
21035                 }
21036                 if (parent) {
21037                     return true;
21038                 }
21039             }
21040
21041             return false;
21042         },
21043
21044         
21045         getLocation: function(oDD) {
21046             if (! this.isTypeOfDD(oDD)) {
21047                 return null;
21048             }
21049
21050             var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
21051
21052             try {
21053                 pos= Ext.lib.Dom.getXY(el);
21054             } catch (e) { }
21055
21056             if (!pos) {
21057                 return null;
21058             }
21059
21060             x1 = pos[0];
21061             x2 = x1 + el.offsetWidth;
21062             y1 = pos[1];
21063             y2 = y1 + el.offsetHeight;
21064
21065             t = y1 - oDD.padding[0];
21066             r = x2 + oDD.padding[1];
21067             b = y2 + oDD.padding[2];
21068             l = x1 - oDD.padding[3];
21069
21070             return new Ext.lib.Region( t, r, b, l );
21071         },
21072
21073         
21074         isOverTarget: function(pt, oTarget, intersect) {
21075             
21076             var loc = this.locationCache[oTarget.id];
21077             if (!loc || !this.useCache) {
21078                 loc = this.getLocation(oTarget);
21079                 this.locationCache[oTarget.id] = loc;
21080
21081             }
21082
21083             if (!loc) {
21084                 return false;
21085             }
21086
21087             oTarget.cursorIsOver = loc.contains( pt );
21088
21089             
21090             
21091             
21092             
21093             
21094             var dc = this.dragCurrent;
21095             if (!dc || !dc.getTargetCoord ||
21096                     (!intersect && !dc.constrainX && !dc.constrainY)) {
21097                 return oTarget.cursorIsOver;
21098             }
21099
21100             oTarget.overlap = null;
21101
21102             
21103             
21104             
21105             
21106             var pos = dc.getTargetCoord(pt.x, pt.y);
21107
21108             var el = dc.getDragEl();
21109             var curRegion = new Ext.lib.Region( pos.y,
21110                                                    pos.x + el.offsetWidth,
21111                                                    pos.y + el.offsetHeight,
21112                                                    pos.x );
21113
21114             var overlap = curRegion.intersect(loc);
21115
21116             if (overlap) {
21117                 oTarget.overlap = overlap;
21118                 return (intersect) ? true : oTarget.cursorIsOver;
21119             } else {
21120                 return false;
21121             }
21122         },
21123
21124         
21125         _onUnload: function(e, me) {
21126             Ext.dd.DragDropMgr.unregAll();
21127         },
21128
21129         
21130         unregAll: function() {
21131
21132             if (this.dragCurrent) {
21133                 this.stopDrag();
21134                 this.dragCurrent = null;
21135             }
21136
21137             this._execOnAll("unreg", []);
21138
21139             for (var i in this.elementCache) {
21140                 delete this.elementCache[i];
21141             }
21142
21143             this.elementCache = {};
21144             this.ids = {};
21145         },
21146
21147         
21148         elementCache: {},
21149
21150         
21151         getElWrapper: function(id) {
21152             var oWrapper = this.elementCache[id];
21153             if (!oWrapper || !oWrapper.el) {
21154                 oWrapper = this.elementCache[id] =
21155                     new this.ElementWrapper(Ext.getDom(id));
21156             }
21157             return oWrapper;
21158         },
21159
21160         
21161         getElement: function(id) {
21162             return Ext.getDom(id);
21163         },
21164
21165         
21166         getCss: function(id) {
21167             var el = Ext.getDom(id);
21168             return (el) ? el.style : null;
21169         },
21170
21171         
21172         ElementWrapper: function(el) {
21173                 
21174                 this.el = el || null;
21175                 
21176                 this.id = this.el && el.id;
21177                 
21178                 this.css = this.el && el.style;
21179             },
21180
21181         
21182         getPosX: function(el) {
21183             return Ext.lib.Dom.getX(el);
21184         },
21185
21186         
21187         getPosY: function(el) {
21188             return Ext.lib.Dom.getY(el);
21189         },
21190
21191         
21192         swapNode: function(n1, n2) {
21193             if (n1.swapNode) {
21194                 n1.swapNode(n2);
21195             } else {
21196                 var p = n2.parentNode;
21197                 var s = n2.nextSibling;
21198
21199                 if (s == n1) {
21200                     p.insertBefore(n1, n2);
21201                 } else if (n2 == n1.nextSibling) {
21202                     p.insertBefore(n2, n1);
21203                 } else {
21204                     n1.parentNode.replaceChild(n2, n1);
21205                     p.insertBefore(n1, s);
21206                 }
21207             }
21208         },
21209
21210         
21211         getScroll: function () {
21212             var t, l, dde=document.documentElement, db=document.body;
21213             if (dde && (dde.scrollTop || dde.scrollLeft)) {
21214                 t = dde.scrollTop;
21215                 l = dde.scrollLeft;
21216             } else if (db) {
21217                 t = db.scrollTop;
21218                 l = db.scrollLeft;
21219             } else {
21220
21221             }
21222             return { top: t, left: l };
21223         },
21224
21225         
21226         getStyle: function(el, styleProp) {
21227             return Ext.fly(el).getStyle(styleProp);
21228         },
21229
21230         
21231         getScrollTop: function () {
21232             return this.getScroll().top;
21233         },
21234
21235         
21236         getScrollLeft: function () {
21237             return this.getScroll().left;
21238         },
21239
21240         
21241         moveToEl: function (moveEl, targetEl) {
21242             var aCoord = Ext.lib.Dom.getXY(targetEl);
21243             Ext.lib.Dom.setXY(moveEl, aCoord);
21244         },
21245
21246         
21247         numericSort: function(a, b) {
21248             return (a - b);
21249         },
21250
21251         
21252         _timeoutCount: 0,
21253
21254         
21255         _addListeners: function() {
21256             var DDM = Ext.dd.DDM;
21257             if ( Ext.lib.Event && document ) {
21258                 DDM._onLoad();
21259             } else {
21260                 if (DDM._timeoutCount > 2000) {
21261                 } else {
21262                     setTimeout(DDM._addListeners, 10);
21263                     if (document && document.body) {
21264                         DDM._timeoutCount += 1;
21265                     }
21266                 }
21267             }
21268         },
21269
21270         
21271         handleWasClicked: function(node, id) {
21272             if (this.isHandle(id, node.id)) {
21273                 return true;
21274             } else {
21275                 
21276                 var p = node.parentNode;
21277
21278                 while (p) {
21279                     if (this.isHandle(id, p.id)) {
21280                         return true;
21281                     } else {
21282                         p = p.parentNode;
21283                     }
21284                 }
21285             }
21286
21287             return false;
21288         }
21289
21290     };
21291
21292 }();
21293
21294
21295 Ext.dd.DDM = Ext.dd.DragDropMgr;
21296 Ext.dd.DDM._addListeners();
21297
21298 }
21299
21300
21301 Ext.dd.DD = function(id, sGroup, config) {
21302     if (id) {
21303         this.init(id, sGroup, config);
21304     }
21305 };
21306
21307 Ext.extend(Ext.dd.DD, Ext.dd.DragDrop, {
21308
21309     
21310     scroll: true,
21311
21312     
21313     autoOffset: function(iPageX, iPageY) {
21314         var x = iPageX - this.startPageX;
21315         var y = iPageY - this.startPageY;
21316         this.setDelta(x, y);
21317     },
21318
21319     
21320     setDelta: function(iDeltaX, iDeltaY) {
21321         this.deltaX = iDeltaX;
21322         this.deltaY = iDeltaY;
21323     },
21324
21325     
21326     setDragElPos: function(iPageX, iPageY) {
21327         
21328         
21329
21330         var el = this.getDragEl();
21331         this.alignElWithMouse(el, iPageX, iPageY);
21332     },
21333
21334     
21335     alignElWithMouse: function(el, iPageX, iPageY) {
21336         var oCoord = this.getTargetCoord(iPageX, iPageY);
21337         var fly = el.dom ? el : Ext.fly(el, '_dd');
21338         if (!this.deltaSetXY) {
21339             var aCoord = [oCoord.x, oCoord.y];
21340             fly.setXY(aCoord);
21341             var newLeft = fly.getLeft(true);
21342             var newTop  = fly.getTop(true);
21343             this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
21344         } else {
21345             fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
21346         }
21347
21348         this.cachePosition(oCoord.x, oCoord.y);
21349         this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
21350         return oCoord;
21351     },
21352
21353     
21354     cachePosition: function(iPageX, iPageY) {
21355         if (iPageX) {
21356             this.lastPageX = iPageX;
21357             this.lastPageY = iPageY;
21358         } else {
21359             var aCoord = Ext.lib.Dom.getXY(this.getEl());
21360             this.lastPageX = aCoord[0];
21361             this.lastPageY = aCoord[1];
21362         }
21363     },
21364
21365     
21366     autoScroll: function(x, y, h, w) {
21367
21368         if (this.scroll) {
21369             
21370             var clientH = Ext.lib.Dom.getViewHeight();
21371
21372             
21373             var clientW = Ext.lib.Dom.getViewWidth();
21374
21375             
21376             var st = this.DDM.getScrollTop();
21377
21378             
21379             var sl = this.DDM.getScrollLeft();
21380
21381             
21382             var bot = h + y;
21383
21384             
21385             var right = w + x;
21386
21387             
21388             
21389             
21390             var toBot = (clientH + st - y - this.deltaY);
21391
21392             
21393             var toRight = (clientW + sl - x - this.deltaX);
21394
21395
21396             
21397             
21398             var thresh = 40;
21399
21400             
21401             
21402             
21403             var scrAmt = (document.all) ? 80 : 30;
21404
21405             
21406             
21407             if ( bot > clientH && toBot < thresh ) {
21408                 window.scrollTo(sl, st + scrAmt);
21409             }
21410
21411             
21412             
21413             if ( y < st && st > 0 && y - st < thresh ) {
21414                 window.scrollTo(sl, st - scrAmt);
21415             }
21416
21417             
21418             
21419             if ( right > clientW && toRight < thresh ) {
21420                 window.scrollTo(sl + scrAmt, st);
21421             }
21422
21423             
21424             
21425             if ( x < sl && sl > 0 && x - sl < thresh ) {
21426                 window.scrollTo(sl - scrAmt, st);
21427             }
21428         }
21429     },
21430
21431     
21432     getTargetCoord: function(iPageX, iPageY) {
21433         var x = iPageX - this.deltaX;
21434         var y = iPageY - this.deltaY;
21435
21436         if (this.constrainX) {
21437             if (x < this.minX) { x = this.minX; }
21438             if (x > this.maxX) { x = this.maxX; }
21439         }
21440
21441         if (this.constrainY) {
21442             if (y < this.minY) { y = this.minY; }
21443             if (y > this.maxY) { y = this.maxY; }
21444         }
21445
21446         x = this.getTick(x, this.xTicks);
21447         y = this.getTick(y, this.yTicks);
21448
21449
21450         return {x:x, y:y};
21451     },
21452
21453     
21454     applyConfig: function() {
21455         Ext.dd.DD.superclass.applyConfig.call(this);
21456         this.scroll = (this.config.scroll !== false);
21457     },
21458
21459     
21460     b4MouseDown: function(e) {
21461         
21462         this.autoOffset(e.getPageX(),
21463                             e.getPageY());
21464     },
21465
21466     
21467     b4Drag: function(e) {
21468         this.setDragElPos(e.getPageX(),
21469                             e.getPageY());
21470     },
21471
21472     toString: function() {
21473         return ("DD " + this.id);
21474     }
21475
21476     
21477     
21478     
21479     
21480
21481 });
21482
21483 Ext.dd.DDProxy = function(id, sGroup, config) {
21484     if (id) {
21485         this.init(id, sGroup, config);
21486         this.initFrame();
21487     }
21488 };
21489
21490
21491 Ext.dd.DDProxy.dragElId = "ygddfdiv";
21492
21493 Ext.extend(Ext.dd.DDProxy, Ext.dd.DD, {
21494
21495     
21496     resizeFrame: true,
21497
21498     
21499     centerFrame: false,
21500
21501     
21502     createFrame: function() {
21503         var self = this;
21504         var body = document.body;
21505
21506         if (!body || !body.firstChild) {
21507             setTimeout( function() { self.createFrame(); }, 50 );
21508             return;
21509         }
21510
21511         var div = this.getDragEl();
21512
21513         if (!div) {
21514             div    = document.createElement("div");
21515             div.id = this.dragElId;
21516             var s  = div.style;
21517
21518             s.position   = "absolute";
21519             s.visibility = "hidden";
21520             s.cursor     = "move";
21521             s.border     = "2px solid #aaa";
21522             s.zIndex     = 999;
21523
21524             
21525             
21526             
21527             body.insertBefore(div, body.firstChild);
21528         }
21529     },
21530
21531     
21532     initFrame: function() {
21533         this.createFrame();
21534     },
21535
21536     applyConfig: function() {
21537         Ext.dd.DDProxy.superclass.applyConfig.call(this);
21538
21539         this.resizeFrame = (this.config.resizeFrame !== false);
21540         this.centerFrame = (this.config.centerFrame);
21541         this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
21542     },
21543
21544     
21545     showFrame: function(iPageX, iPageY) {
21546         var el = this.getEl();
21547         var dragEl = this.getDragEl();
21548         var s = dragEl.style;
21549
21550         this._resizeProxy();
21551
21552         if (this.centerFrame) {
21553             this.setDelta( Math.round(parseInt(s.width,  10)/2),
21554                            Math.round(parseInt(s.height, 10)/2) );
21555         }
21556
21557         this.setDragElPos(iPageX, iPageY);
21558
21559         Ext.fly(dragEl).show();
21560     },
21561
21562     
21563     _resizeProxy: function() {
21564         if (this.resizeFrame) {
21565             var el = this.getEl();
21566             Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
21567         }
21568     },
21569
21570     
21571     b4MouseDown: function(e) {
21572         var x = e.getPageX();
21573         var y = e.getPageY();
21574         this.autoOffset(x, y);
21575         this.setDragElPos(x, y);
21576     },
21577
21578     
21579     b4StartDrag: function(x, y) {
21580         
21581         this.showFrame(x, y);
21582     },
21583
21584     
21585     b4EndDrag: function(e) {
21586         Ext.fly(this.getDragEl()).hide();
21587     },
21588
21589     
21590     
21591     
21592     endDrag: function(e) {
21593
21594         var lel = this.getEl();
21595         var del = this.getDragEl();
21596
21597         
21598         del.style.visibility = "";
21599
21600         this.beforeMove();
21601         
21602         
21603         lel.style.visibility = "hidden";
21604         Ext.dd.DDM.moveToEl(lel, del);
21605         del.style.visibility = "hidden";
21606         lel.style.visibility = "";
21607
21608         this.afterDrag();
21609     },
21610
21611     beforeMove : function(){
21612
21613     },
21614
21615     afterDrag : function(){
21616
21617     },
21618
21619     toString: function() {
21620         return ("DDProxy " + this.id);
21621     }
21622
21623 });
21624
21625 Ext.dd.DDTarget = function(id, sGroup, config) {
21626     if (id) {
21627         this.initTarget(id, sGroup, config);
21628     }
21629 };
21630
21631
21632 Ext.extend(Ext.dd.DDTarget, Ext.dd.DragDrop, {
21633     
21634     getDragEl: Ext.emptyFn,
21635     
21636     isValidHandleChild: Ext.emptyFn,
21637     
21638     startDrag: Ext.emptyFn,
21639     
21640     endDrag: Ext.emptyFn,
21641     
21642     onDrag: Ext.emptyFn,
21643     
21644     onDragDrop: Ext.emptyFn,
21645     
21646     onDragEnter: Ext.emptyFn,
21647     
21648     onDragOut: Ext.emptyFn,
21649     
21650     onDragOver: Ext.emptyFn,
21651     
21652     onInvalidDrop: Ext.emptyFn,
21653     
21654     onMouseDown: Ext.emptyFn,
21655     
21656     onMouseUp: Ext.emptyFn,
21657     
21658     setXConstraint: Ext.emptyFn,
21659     
21660     setYConstraint: Ext.emptyFn,
21661     
21662     resetConstraints: Ext.emptyFn,
21663     
21664     clearConstraints: Ext.emptyFn,
21665     
21666     clearTicks: Ext.emptyFn,
21667     
21668     setInitPosition: Ext.emptyFn,
21669     
21670     setDragElId: Ext.emptyFn,
21671     
21672     setHandleElId: Ext.emptyFn,
21673     
21674     setOuterHandleElId: Ext.emptyFn,
21675     
21676     addInvalidHandleClass: Ext.emptyFn,
21677     
21678     addInvalidHandleId: Ext.emptyFn,
21679     
21680     addInvalidHandleType: Ext.emptyFn,
21681     
21682     removeInvalidHandleClass: Ext.emptyFn,
21683     
21684     removeInvalidHandleId: Ext.emptyFn,
21685     
21686     removeInvalidHandleType: Ext.emptyFn,
21687
21688     toString: function() {
21689         return ("DDTarget " + this.id);
21690     }
21691 });
21692 Ext.dd.DragTracker = Ext.extend(Ext.util.Observable,  {    
21693         
21694     active: false,
21695         
21696     tolerance: 5,
21697         
21698     autoStart: false,
21699     
21700     constructor : function(config){
21701         Ext.apply(this, config);
21702             this.addEvents(
21703                 
21704                 'mousedown',
21705                 
21706                 'mouseup',
21707                 
21708                 'mousemove',
21709                 
21710                 'dragstart',
21711                 
21712                 'dragend',
21713                 
21714                 'drag'
21715             );
21716         
21717             this.dragRegion = new Ext.lib.Region(0,0,0,0);
21718         
21719             if(this.el){
21720                 this.initEl(this.el);
21721             }
21722         Ext.dd.DragTracker.superclass.constructor.call(this, config);
21723     },
21724
21725     initEl: function(el){
21726         this.el = Ext.get(el);
21727         el.on('mousedown', this.onMouseDown, this,
21728                 this.delegate ? {delegate: this.delegate} : undefined);
21729     },
21730
21731     destroy : function(){
21732         this.el.un('mousedown', this.onMouseDown, this);
21733         delete this.el;
21734     },
21735
21736     onMouseDown: function(e, target){
21737         if(this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false){
21738             this.startXY = this.lastXY = e.getXY();
21739             this.dragTarget = this.delegate ? target : this.el.dom;
21740             if(this.preventDefault !== false){
21741                 e.preventDefault();
21742             }
21743             Ext.getDoc().on({
21744                 scope: this,
21745                 mouseup: this.onMouseUp,
21746                 mousemove: this.onMouseMove,
21747                 selectstart: this.stopSelect
21748             });
21749             if(this.autoStart){
21750                 this.timer = this.triggerStart.defer(this.autoStart === true ? 1000 : this.autoStart, this, [e]);
21751             }
21752         }
21753     },
21754
21755     onMouseMove: function(e, target){
21756         
21757         if(this.active && Ext.isIE && !e.browserEvent.button){
21758             e.preventDefault();
21759             this.onMouseUp(e);
21760             return;
21761         }
21762
21763         e.preventDefault();
21764         var xy = e.getXY(), s = this.startXY;
21765         this.lastXY = xy;
21766         if(!this.active){
21767             if(Math.abs(s[0]-xy[0]) > this.tolerance || Math.abs(s[1]-xy[1]) > this.tolerance){
21768                 this.triggerStart(e);
21769             }else{
21770                 return;
21771             }
21772         }
21773         this.fireEvent('mousemove', this, e);
21774         this.onDrag(e);
21775         this.fireEvent('drag', this, e);
21776     },
21777
21778     onMouseUp: function(e) {
21779         var doc = Ext.getDoc(),
21780             wasActive = this.active;
21781             
21782         doc.un('mousemove', this.onMouseMove, this);
21783         doc.un('mouseup', this.onMouseUp, this);
21784         doc.un('selectstart', this.stopSelect, this);
21785         e.preventDefault();
21786         this.clearStart();
21787         this.active = false;
21788         delete this.elRegion;
21789         this.fireEvent('mouseup', this, e);
21790         if(wasActive){
21791             this.onEnd(e);
21792             this.fireEvent('dragend', this, e);
21793         }
21794     },
21795
21796     triggerStart: function(e) {
21797         this.clearStart();
21798         this.active = true;
21799         this.onStart(e);
21800         this.fireEvent('dragstart', this, e);
21801     },
21802
21803     clearStart : function() {
21804         if(this.timer){
21805             clearTimeout(this.timer);
21806             delete this.timer;
21807         }
21808     },
21809
21810     stopSelect : function(e) {
21811         e.stopEvent();
21812         return false;
21813     },
21814     
21815     
21816     onBeforeStart : function(e) {
21817
21818     },
21819
21820     
21821     onStart : function(xy) {
21822
21823     },
21824
21825     
21826     onDrag : function(e) {
21827
21828     },
21829
21830     
21831     onEnd : function(e) {
21832
21833     },
21834
21835     
21836     getDragTarget : function(){
21837         return this.dragTarget;
21838     },
21839
21840     getDragCt : function(){
21841         return this.el;
21842     },
21843
21844     getXY : function(constrain){
21845         return constrain ?
21846                this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;
21847     },
21848
21849     getOffset : function(constrain){
21850         var xy = this.getXY(constrain),
21851             s = this.startXY;
21852         return [s[0]-xy[0], s[1]-xy[1]];
21853     },
21854
21855     constrainModes: {
21856         'point' : function(xy){
21857
21858             if(!this.elRegion){
21859                 this.elRegion = this.getDragCt().getRegion();
21860             }
21861
21862             var dr = this.dragRegion;
21863
21864             dr.left = xy[0];
21865             dr.top = xy[1];
21866             dr.right = xy[0];
21867             dr.bottom = xy[1];
21868
21869             dr.constrainTo(this.elRegion);
21870
21871             return [dr.left, dr.top];
21872         }
21873     }
21874 });
21875 Ext.dd.ScrollManager = function(){
21876     var ddm = Ext.dd.DragDropMgr;
21877     var els = {};
21878     var dragEl = null;
21879     var proc = {};
21880     
21881     var onStop = function(e){
21882         dragEl = null;
21883         clearProc();
21884     };
21885     
21886     var triggerRefresh = function(){
21887         if(ddm.dragCurrent){
21888              ddm.refreshCache(ddm.dragCurrent.groups);
21889         }
21890     };
21891     
21892     var doScroll = function(){
21893         if(ddm.dragCurrent){
21894             var dds = Ext.dd.ScrollManager;
21895             var inc = proc.el.ddScrollConfig ?
21896                       proc.el.ddScrollConfig.increment : dds.increment;
21897             if(!dds.animate){
21898                 if(proc.el.scroll(proc.dir, inc)){
21899                     triggerRefresh();
21900                 }
21901             }else{
21902                 proc.el.scroll(proc.dir, inc, true, dds.animDuration, triggerRefresh);
21903             }
21904         }
21905     };
21906     
21907     var clearProc = function(){
21908         if(proc.id){
21909             clearInterval(proc.id);
21910         }
21911         proc.id = 0;
21912         proc.el = null;
21913         proc.dir = "";
21914     };
21915
21916     var startProc = function(el, dir){
21917         clearProc();
21918         proc.el = el;
21919         proc.dir = dir;
21920         var group = el.ddScrollConfig ? el.ddScrollConfig.ddGroup : undefined,
21921             freq  = (el.ddScrollConfig && el.ddScrollConfig.frequency)
21922                   ? el.ddScrollConfig.frequency
21923                   : Ext.dd.ScrollManager.frequency;
21924
21925         if (group === undefined || ddm.dragCurrent.ddGroup == group) {
21926             proc.id = setInterval(doScroll, freq);
21927         }
21928     };
21929     
21930     var onFire = function(e, isDrop){
21931         if(isDrop || !ddm.dragCurrent){ return; }
21932         var dds = Ext.dd.ScrollManager;
21933         if(!dragEl || dragEl != ddm.dragCurrent){
21934             dragEl = ddm.dragCurrent;
21935             
21936             dds.refreshCache();
21937         }
21938         
21939         var xy = Ext.lib.Event.getXY(e);
21940         var pt = new Ext.lib.Point(xy[0], xy[1]);
21941         for(var id in els){
21942             var el = els[id], r = el._region;
21943             var c = el.ddScrollConfig ? el.ddScrollConfig : dds;
21944             if(r && r.contains(pt) && el.isScrollable()){
21945                 if(r.bottom - pt.y <= c.vthresh){
21946                     if(proc.el != el){
21947                         startProc(el, "down");
21948                     }
21949                     return;
21950                 }else if(r.right - pt.x <= c.hthresh){
21951                     if(proc.el != el){
21952                         startProc(el, "left");
21953                     }
21954                     return;
21955                 }else if(pt.y - r.top <= c.vthresh){
21956                     if(proc.el != el){
21957                         startProc(el, "up");
21958                     }
21959                     return;
21960                 }else if(pt.x - r.left <= c.hthresh){
21961                     if(proc.el != el){
21962                         startProc(el, "right");
21963                     }
21964                     return;
21965                 }
21966             }
21967         }
21968         clearProc();
21969     };
21970     
21971     ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
21972     ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
21973     
21974     return {
21975         
21976         register : function(el){
21977             if(Ext.isArray(el)){
21978                 for(var i = 0, len = el.length; i < len; i++) {
21979                         this.register(el[i]);
21980                 }
21981             }else{
21982                 el = Ext.get(el);
21983                 els[el.id] = el;
21984             }
21985         },
21986         
21987         
21988         unregister : function(el){
21989             if(Ext.isArray(el)){
21990                 for(var i = 0, len = el.length; i < len; i++) {
21991                         this.unregister(el[i]);
21992                 }
21993             }else{
21994                 el = Ext.get(el);
21995                 delete els[el.id];
21996             }
21997         },
21998         
21999         
22000         vthresh : 25,
22001         
22002         hthresh : 25,
22003
22004         
22005         increment : 100,
22006         
22007         
22008         frequency : 500,
22009         
22010         
22011         animate: true,
22012         
22013         
22014         animDuration: .4,
22015         
22016         
22017         ddGroup: undefined,
22018         
22019         
22020         refreshCache : function(){
22021             for(var id in els){
22022                 if(typeof els[id] == 'object'){ 
22023                     els[id]._region = els[id].getRegion();
22024                 }
22025             }
22026         }
22027     };
22028 }();
22029 Ext.dd.Registry = function(){
22030     var elements = {}; 
22031     var handles = {}; 
22032     var autoIdSeed = 0;
22033
22034     var getId = function(el, autogen){
22035         if(typeof el == "string"){
22036             return el;
22037         }
22038         var id = el.id;
22039         if(!id && autogen !== false){
22040             id = "extdd-" + (++autoIdSeed);
22041             el.id = id;
22042         }
22043         return id;
22044     };
22045     
22046     return {
22047     
22048         register : function(el, data){
22049             data = data || {};
22050             if(typeof el == "string"){
22051                 el = document.getElementById(el);
22052             }
22053             data.ddel = el;
22054             elements[getId(el)] = data;
22055             if(data.isHandle !== false){
22056                 handles[data.ddel.id] = data;
22057             }
22058             if(data.handles){
22059                 var hs = data.handles;
22060                 for(var i = 0, len = hs.length; i < len; i++){
22061                         handles[getId(hs[i])] = data;
22062                 }
22063             }
22064         },
22065
22066     
22067         unregister : function(el){
22068             var id = getId(el, false);
22069             var data = elements[id];
22070             if(data){
22071                 delete elements[id];
22072                 if(data.handles){
22073                     var hs = data.handles;
22074                     for(var i = 0, len = hs.length; i < len; i++){
22075                         delete handles[getId(hs[i], false)];
22076                     }
22077                 }
22078             }
22079         },
22080
22081     
22082         getHandle : function(id){
22083             if(typeof id != "string"){ 
22084                 id = id.id;
22085             }
22086             return handles[id];
22087         },
22088
22089     
22090         getHandleFromEvent : function(e){
22091             var t = Ext.lib.Event.getTarget(e);
22092             return t ? handles[t.id] : null;
22093         },
22094
22095     
22096         getTarget : function(id){
22097             if(typeof id != "string"){ 
22098                 id = id.id;
22099             }
22100             return elements[id];
22101         },
22102
22103     
22104         getTargetFromEvent : function(e){
22105             var t = Ext.lib.Event.getTarget(e);
22106             return t ? elements[t.id] || handles[t.id] : null;
22107         }
22108     };
22109 }();
22110 Ext.dd.StatusProxy = function(config){
22111     Ext.apply(this, config);
22112     this.id = this.id || Ext.id();
22113     this.el = new Ext.Layer({
22114         dh: {
22115             id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
22116                 {tag: "div", cls: "x-dd-drop-icon"},
22117                 {tag: "div", cls: "x-dd-drag-ghost"}
22118             ]
22119         }, 
22120         shadow: !config || config.shadow !== false
22121     });
22122     this.ghost = Ext.get(this.el.dom.childNodes[1]);
22123     this.dropStatus = this.dropNotAllowed;
22124 };
22125
22126 Ext.dd.StatusProxy.prototype = {
22127     
22128     dropAllowed : "x-dd-drop-ok",
22129     
22130     dropNotAllowed : "x-dd-drop-nodrop",
22131
22132     
22133     setStatus : function(cssClass){
22134         cssClass = cssClass || this.dropNotAllowed;
22135         if(this.dropStatus != cssClass){
22136             this.el.replaceClass(this.dropStatus, cssClass);
22137             this.dropStatus = cssClass;
22138         }
22139     },
22140
22141     
22142     reset : function(clearGhost){
22143         this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
22144         this.dropStatus = this.dropNotAllowed;
22145         if(clearGhost){
22146             this.ghost.update("");
22147         }
22148     },
22149
22150     
22151     update : function(html){
22152         if(typeof html == "string"){
22153             this.ghost.update(html);
22154         }else{
22155             this.ghost.update("");
22156             html.style.margin = "0";
22157             this.ghost.dom.appendChild(html);
22158         }
22159         var el = this.ghost.dom.firstChild; 
22160         if(el){
22161             Ext.fly(el).setStyle('float', 'none');
22162         }
22163     },
22164
22165     
22166     getEl : function(){
22167         return this.el;
22168     },
22169
22170     
22171     getGhost : function(){
22172         return this.ghost;
22173     },
22174
22175     
22176     hide : function(clear){
22177         this.el.hide();
22178         if(clear){
22179             this.reset(true);
22180         }
22181     },
22182
22183     
22184     stop : function(){
22185         if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
22186             this.anim.stop();
22187         }
22188     },
22189
22190     
22191     show : function(){
22192         this.el.show();
22193     },
22194
22195     
22196     sync : function(){
22197         this.el.sync();
22198     },
22199
22200     
22201     repair : function(xy, callback, scope){
22202         this.callback = callback;
22203         this.scope = scope;
22204         if(xy && this.animRepair !== false){
22205             this.el.addClass("x-dd-drag-repair");
22206             this.el.hideUnders(true);
22207             this.anim = this.el.shift({
22208                 duration: this.repairDuration || .5,
22209                 easing: 'easeOut',
22210                 xy: xy,
22211                 stopFx: true,
22212                 callback: this.afterRepair,
22213                 scope: this
22214             });
22215         }else{
22216             this.afterRepair();
22217         }
22218     },
22219
22220     
22221     afterRepair : function(){
22222         this.hide(true);
22223         if(typeof this.callback == "function"){
22224             this.callback.call(this.scope || this);
22225         }
22226         this.callback = null;
22227         this.scope = null;
22228     },
22229     
22230     destroy: function(){
22231         Ext.destroy(this.ghost, this.el);    
22232     }
22233 };
22234 Ext.dd.DragSource = function(el, config){
22235     this.el = Ext.get(el);
22236     if(!this.dragData){
22237         this.dragData = {};
22238     }
22239     
22240     Ext.apply(this, config);
22241     
22242     if(!this.proxy){
22243         this.proxy = new Ext.dd.StatusProxy();
22244     }
22245     Ext.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
22246           {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
22247     
22248     this.dragging = false;
22249 };
22250
22251 Ext.extend(Ext.dd.DragSource, Ext.dd.DDProxy, {
22252     
22253     
22254     dropAllowed : "x-dd-drop-ok",
22255     
22256     dropNotAllowed : "x-dd-drop-nodrop",
22257
22258     
22259     getDragData : function(e){
22260         return this.dragData;
22261     },
22262
22263     
22264     onDragEnter : function(e, id){
22265         var target = Ext.dd.DragDropMgr.getDDById(id);
22266         this.cachedTarget = target;
22267         if(this.beforeDragEnter(target, e, id) !== false){
22268             if(target.isNotifyTarget){
22269                 var status = target.notifyEnter(this, e, this.dragData);
22270                 this.proxy.setStatus(status);
22271             }else{
22272                 this.proxy.setStatus(this.dropAllowed);
22273             }
22274             
22275             if(this.afterDragEnter){
22276                 
22277                 this.afterDragEnter(target, e, id);
22278             }
22279         }
22280     },
22281
22282     
22283     beforeDragEnter : function(target, e, id){
22284         return true;
22285     },
22286
22287     
22288     alignElWithMouse: function() {
22289         Ext.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
22290         this.proxy.sync();
22291     },
22292
22293     
22294     onDragOver : function(e, id){
22295         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
22296         if(this.beforeDragOver(target, e, id) !== false){
22297             if(target.isNotifyTarget){
22298                 var status = target.notifyOver(this, e, this.dragData);
22299                 this.proxy.setStatus(status);
22300             }
22301
22302             if(this.afterDragOver){
22303                 
22304                 this.afterDragOver(target, e, id);
22305             }
22306         }
22307     },
22308
22309     
22310     beforeDragOver : function(target, e, id){
22311         return true;
22312     },
22313
22314     
22315     onDragOut : function(e, id){
22316         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
22317         if(this.beforeDragOut(target, e, id) !== false){
22318             if(target.isNotifyTarget){
22319                 target.notifyOut(this, e, this.dragData);
22320             }
22321             this.proxy.reset();
22322             if(this.afterDragOut){
22323                 
22324                 this.afterDragOut(target, e, id);
22325             }
22326         }
22327         this.cachedTarget = null;
22328     },
22329
22330     
22331     beforeDragOut : function(target, e, id){
22332         return true;
22333     },
22334     
22335     
22336     onDragDrop : function(e, id){
22337         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
22338         if(this.beforeDragDrop(target, e, id) !== false){
22339             if(target.isNotifyTarget){
22340                 if(target.notifyDrop(this, e, this.dragData)){ 
22341                     this.onValidDrop(target, e, id);
22342                 }else{
22343                     this.onInvalidDrop(target, e, id);
22344                 }
22345             }else{
22346                 this.onValidDrop(target, e, id);
22347             }
22348             
22349             if(this.afterDragDrop){
22350                 
22351                 this.afterDragDrop(target, e, id);
22352             }
22353         }
22354         delete this.cachedTarget;
22355     },
22356
22357     
22358     beforeDragDrop : function(target, e, id){
22359         return true;
22360     },
22361
22362     
22363     onValidDrop : function(target, e, id){
22364         this.hideProxy();
22365         if(this.afterValidDrop){
22366             
22367             this.afterValidDrop(target, e, id);
22368         }
22369     },
22370
22371     
22372     getRepairXY : function(e, data){
22373         return this.el.getXY();  
22374     },
22375
22376     
22377     onInvalidDrop : function(target, e, id){
22378         this.beforeInvalidDrop(target, e, id);
22379         if(this.cachedTarget){
22380             if(this.cachedTarget.isNotifyTarget){
22381                 this.cachedTarget.notifyOut(this, e, this.dragData);
22382             }
22383             this.cacheTarget = null;
22384         }
22385         this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
22386
22387         if(this.afterInvalidDrop){
22388             
22389             this.afterInvalidDrop(e, id);
22390         }
22391     },
22392
22393     
22394     afterRepair : function(){
22395         if(Ext.enableFx){
22396             this.el.highlight(this.hlColor || "c3daf9");
22397         }
22398         this.dragging = false;
22399     },
22400
22401     
22402     beforeInvalidDrop : function(target, e, id){
22403         return true;
22404     },
22405
22406     
22407     handleMouseDown : function(e){
22408         if(this.dragging) {
22409             return;
22410         }
22411         var data = this.getDragData(e);
22412         if(data && this.onBeforeDrag(data, e) !== false){
22413             this.dragData = data;
22414             this.proxy.stop();
22415             Ext.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
22416         } 
22417     },
22418
22419     
22420     onBeforeDrag : function(data, e){
22421         return true;
22422     },
22423
22424     
22425     onStartDrag : Ext.emptyFn,
22426
22427     
22428     startDrag : function(x, y){
22429         this.proxy.reset();
22430         this.dragging = true;
22431         this.proxy.update("");
22432         this.onInitDrag(x, y);
22433         this.proxy.show();
22434     },
22435
22436     
22437     onInitDrag : function(x, y){
22438         var clone = this.el.dom.cloneNode(true);
22439         clone.id = Ext.id(); 
22440         this.proxy.update(clone);
22441         this.onStartDrag(x, y);
22442         return true;
22443     },
22444
22445     
22446     getProxy : function(){
22447         return this.proxy;  
22448     },
22449
22450     
22451     hideProxy : function(){
22452         this.proxy.hide();  
22453         this.proxy.reset(true);
22454         this.dragging = false;
22455     },
22456
22457     
22458     triggerCacheRefresh : function(){
22459         Ext.dd.DDM.refreshCache(this.groups);
22460     },
22461
22462     
22463     b4EndDrag: function(e) {
22464     },
22465
22466     
22467     endDrag : function(e){
22468         this.onEndDrag(this.dragData, e);
22469     },
22470
22471     
22472     onEndDrag : function(data, e){
22473     },
22474     
22475     
22476     autoOffset : function(x, y) {
22477         this.setDelta(-12, -20);
22478     },
22479     
22480     destroy: function(){
22481         Ext.dd.DragSource.superclass.destroy.call(this);
22482         Ext.destroy(this.proxy);
22483     }
22484 });
22485 Ext.dd.DropTarget = Ext.extend(Ext.dd.DDTarget, {
22486     
22487     constructor : function(el, config){
22488         this.el = Ext.get(el);
22489     
22490         Ext.apply(this, config);
22491     
22492         if(this.containerScroll){
22493             Ext.dd.ScrollManager.register(this.el);
22494         }
22495     
22496         Ext.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
22497               {isTarget: true});        
22498     },
22499     
22500     
22501     
22502     
22503     dropAllowed : "x-dd-drop-ok",
22504     
22505     dropNotAllowed : "x-dd-drop-nodrop",
22506
22507     
22508     isTarget : true,
22509
22510     
22511     isNotifyTarget : true,
22512
22513     
22514     notifyEnter : function(dd, e, data){
22515         if(this.overClass){
22516             this.el.addClass(this.overClass);
22517         }
22518         return this.dropAllowed;
22519     },
22520
22521     
22522     notifyOver : function(dd, e, data){
22523         return this.dropAllowed;
22524     },
22525
22526     
22527     notifyOut : function(dd, e, data){
22528         if(this.overClass){
22529             this.el.removeClass(this.overClass);
22530         }
22531     },
22532
22533     
22534     notifyDrop : function(dd, e, data){
22535         return false;
22536     },
22537     
22538     destroy : function(){
22539         Ext.dd.DropTarget.superclass.destroy.call(this);
22540         if(this.containerScroll){
22541             Ext.dd.ScrollManager.unregister(this.el);
22542         }
22543     }
22544 });
22545 Ext.dd.DragZone = Ext.extend(Ext.dd.DragSource, {
22546     
22547     constructor : function(el, config){
22548         Ext.dd.DragZone.superclass.constructor.call(this, el, config);
22549         if(this.containerScroll){
22550             Ext.dd.ScrollManager.register(this.el);
22551         }
22552     },
22553     
22554     
22555     
22556     
22557
22558     
22559     getDragData : function(e){
22560         return Ext.dd.Registry.getHandleFromEvent(e);
22561     },
22562     
22563     
22564     onInitDrag : function(x, y){
22565         this.proxy.update(this.dragData.ddel.cloneNode(true));
22566         this.onStartDrag(x, y);
22567         return true;
22568     },
22569     
22570     
22571     afterRepair : function(){
22572         if(Ext.enableFx){
22573             Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
22574         }
22575         this.dragging = false;
22576     },
22577
22578     
22579     getRepairXY : function(e){
22580         return Ext.Element.fly(this.dragData.ddel).getXY();  
22581     },
22582     
22583     destroy : function(){
22584         Ext.dd.DragZone.superclass.destroy.call(this);
22585         if(this.containerScroll){
22586             Ext.dd.ScrollManager.unregister(this.el);
22587         }
22588     }
22589 });
22590 Ext.dd.DropZone = function(el, config){
22591     Ext.dd.DropZone.superclass.constructor.call(this, el, config);
22592 };
22593
22594 Ext.extend(Ext.dd.DropZone, Ext.dd.DropTarget, {
22595     
22596     getTargetFromEvent : function(e){
22597         return Ext.dd.Registry.getTargetFromEvent(e);
22598     },
22599
22600     
22601     onNodeEnter : function(n, dd, e, data){
22602         
22603     },
22604
22605     
22606     onNodeOver : function(n, dd, e, data){
22607         return this.dropAllowed;
22608     },
22609
22610     
22611     onNodeOut : function(n, dd, e, data){
22612         
22613     },
22614
22615     
22616     onNodeDrop : function(n, dd, e, data){
22617         return false;
22618     },
22619
22620     
22621     onContainerOver : function(dd, e, data){
22622         return this.dropNotAllowed;
22623     },
22624
22625     
22626     onContainerDrop : function(dd, e, data){
22627         return false;
22628     },
22629
22630     
22631     notifyEnter : function(dd, e, data){
22632         return this.dropNotAllowed;
22633     },
22634
22635     
22636     notifyOver : function(dd, e, data){
22637         var n = this.getTargetFromEvent(e);
22638         if(!n){ 
22639             if(this.lastOverNode){
22640                 this.onNodeOut(this.lastOverNode, dd, e, data);
22641                 this.lastOverNode = null;
22642             }
22643             return this.onContainerOver(dd, e, data);
22644         }
22645         if(this.lastOverNode != n){
22646             if(this.lastOverNode){
22647                 this.onNodeOut(this.lastOverNode, dd, e, data);
22648             }
22649             this.onNodeEnter(n, dd, e, data);
22650             this.lastOverNode = n;
22651         }
22652         return this.onNodeOver(n, dd, e, data);
22653     },
22654
22655     
22656     notifyOut : function(dd, e, data){
22657         if(this.lastOverNode){
22658             this.onNodeOut(this.lastOverNode, dd, e, data);
22659             this.lastOverNode = null;
22660         }
22661     },
22662
22663     
22664     notifyDrop : function(dd, e, data){
22665         if(this.lastOverNode){
22666             this.onNodeOut(this.lastOverNode, dd, e, data);
22667             this.lastOverNode = null;
22668         }
22669         var n = this.getTargetFromEvent(e);
22670         return n ?
22671             this.onNodeDrop(n, dd, e, data) :
22672             this.onContainerDrop(dd, e, data);
22673     },
22674
22675     
22676     triggerCacheRefresh : function(){
22677         Ext.dd.DDM.refreshCache(this.groups);
22678     }  
22679 });
22680 Ext.Element.addMethods({
22681     
22682     initDD : function(group, config, overrides){
22683         var dd = new Ext.dd.DD(Ext.id(this.dom), group, config);
22684         return Ext.apply(dd, overrides);
22685     },
22686
22687     
22688     initDDProxy : function(group, config, overrides){
22689         var dd = new Ext.dd.DDProxy(Ext.id(this.dom), group, config);
22690         return Ext.apply(dd, overrides);
22691     },
22692
22693     
22694     initDDTarget : function(group, config, overrides){
22695         var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config);
22696         return Ext.apply(dd, overrides);
22697     }
22698 });
22699
22700 Ext.data.Api = (function() {
22701
22702     
22703     
22704     
22705     
22706     var validActions = {};
22707
22708     return {
22709         
22710         actions : {
22711             create  : 'create',
22712             read    : 'read',
22713             update  : 'update',
22714             destroy : 'destroy'
22715         },
22716
22717         
22718         restActions : {
22719             create  : 'POST',
22720             read    : 'GET',
22721             update  : 'PUT',
22722             destroy : 'DELETE'
22723         },
22724
22725         
22726         isAction : function(action) {
22727             return (Ext.data.Api.actions[action]) ? true : false;
22728         },
22729
22730         
22731         getVerb : function(name) {
22732             if (validActions[name]) {
22733                 return validActions[name];  
22734             }
22735             for (var verb in this.actions) {
22736                 if (this.actions[verb] === name) {
22737                     validActions[name] = verb;
22738                     break;
22739                 }
22740             }
22741             return (validActions[name] !== undefined) ? validActions[name] : null;
22742         },
22743
22744         
22745         isValid : function(api){
22746             var invalid = [];
22747             var crud = this.actions; 
22748             for (var action in api) {
22749                 if (!(action in crud)) {
22750                     invalid.push(action);
22751                 }
22752             }
22753             return (!invalid.length) ? true : invalid;
22754         },
22755
22756         
22757         hasUniqueUrl : function(proxy, verb) {
22758             var url = (proxy.api[verb]) ? proxy.api[verb].url : null;
22759             var unique = true;
22760             for (var action in proxy.api) {
22761                 if ((unique = (action === verb) ? true : (proxy.api[action].url != url) ? true : false) === false) {
22762                     break;
22763                 }
22764             }
22765             return unique;
22766         },
22767
22768         
22769         prepare : function(proxy) {
22770             if (!proxy.api) {
22771                 proxy.api = {}; 
22772             }
22773             for (var verb in this.actions) {
22774                 var action = this.actions[verb];
22775                 proxy.api[action] = proxy.api[action] || proxy.url || proxy.directFn;
22776                 if (typeof(proxy.api[action]) == 'string') {
22777                     proxy.api[action] = {
22778                         url: proxy.api[action],
22779                         method: (proxy.restful === true) ? Ext.data.Api.restActions[action] : undefined
22780                     };
22781                 }
22782             }
22783         },
22784
22785         
22786         restify : function(proxy) {
22787             proxy.restful = true;
22788             for (var verb in this.restActions) {
22789                 proxy.api[this.actions[verb]].method ||
22790                     (proxy.api[this.actions[verb]].method = this.restActions[verb]);
22791             }
22792             
22793             
22794             proxy.onWrite = proxy.onWrite.createInterceptor(function(action, o, response, rs) {
22795                 var reader = o.reader;
22796                 var res = new Ext.data.Response({
22797                     action: action,
22798                     raw: response
22799                 });
22800
22801                 switch (response.status) {
22802                     case 200:   
22803                         return true;
22804                         break;
22805                     case 201:   
22806                         if (Ext.isEmpty(res.raw.responseText)) {
22807                           res.success = true;
22808                         } else {
22809                           
22810                           return true;
22811                         }
22812                         break;
22813                     case 204:  
22814                         res.success = true;
22815                         res.data = null;
22816                         break;
22817                     default:
22818                         return true;
22819                         break;
22820                 }
22821                 if (res.success === true) {
22822                     this.fireEvent("write", this, action, res.data, res, rs, o.request.arg);
22823                 } else {
22824                     this.fireEvent('exception', this, 'remote', action, o, res, rs);
22825                 }
22826                 o.request.callback.call(o.request.scope, res.data, res, res.success);
22827
22828                 return false;   
22829             }, proxy);
22830         }
22831     };
22832 })();
22833
22834
22835 Ext.data.Response = function(params, response) {
22836     Ext.apply(this, params, {
22837         raw: response
22838     });
22839 };
22840 Ext.data.Response.prototype = {
22841     message : null,
22842     success : false,
22843     status : null,
22844     root : null,
22845     raw : null,
22846
22847     getMessage : function() {
22848         return this.message;
22849     },
22850     getSuccess : function() {
22851         return this.success;
22852     },
22853     getStatus : function() {
22854         return this.status;
22855     },
22856     getRoot : function() {
22857         return this.root;
22858     },
22859     getRawResponse : function() {
22860         return this.raw;
22861     }
22862 };
22863
22864
22865 Ext.data.Api.Error = Ext.extend(Ext.Error, {
22866     constructor : function(message, arg) {
22867         this.arg = arg;
22868         Ext.Error.call(this, message);
22869     },
22870     name: 'Ext.data.Api'
22871 });
22872 Ext.apply(Ext.data.Api.Error.prototype, {
22873     lang: {
22874         'action-url-undefined': 'No fallback url defined for this action.  When defining a DataProxy api, please be sure to define an url for each CRUD action in Ext.data.Api.actions or define a default url in addition to your api-configuration.',
22875         'invalid': 'received an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions defined in Ext.data.Api.actions',
22876         'invalid-url': 'Invalid url.  Please review your proxy configuration.',
22877         'execute': 'Attempted to execute an unknown action.  Valid API actions are defined in Ext.data.Api.actions"'
22878     }
22879 });
22880
22881
22882
22883
22884 Ext.data.SortTypes = {
22885     
22886     none : function(s){
22887         return s;
22888     },
22889     
22890     
22891     stripTagsRE : /<\/?[^>]+>/gi,
22892     
22893     
22894     asText : function(s){
22895         return String(s).replace(this.stripTagsRE, "");
22896     },
22897     
22898     
22899     asUCText : function(s){
22900         return String(s).toUpperCase().replace(this.stripTagsRE, "");
22901     },
22902     
22903     
22904     asUCString : function(s) {
22905         return String(s).toUpperCase();
22906     },
22907     
22908     
22909     asDate : function(s) {
22910         if(!s){
22911             return 0;
22912         }
22913         if(Ext.isDate(s)){
22914             return s.getTime();
22915         }
22916         return Date.parse(String(s));
22917     },
22918     
22919     
22920     asFloat : function(s) {
22921         var val = parseFloat(String(s).replace(/,/g, ""));
22922         return isNaN(val) ? 0 : val;
22923     },
22924     
22925     
22926     asInt : function(s) {
22927         var val = parseInt(String(s).replace(/,/g, ""), 10);
22928         return isNaN(val) ? 0 : val;
22929     }
22930 };
22931 Ext.data.Record = function(data, id){
22932     
22933     this.id = (id || id === 0) ? id : Ext.data.Record.id(this);
22934     this.data = data || {};
22935 };
22936
22937
22938 Ext.data.Record.create = function(o){
22939     var f = Ext.extend(Ext.data.Record, {});
22940     var p = f.prototype;
22941     p.fields = new Ext.util.MixedCollection(false, function(field){
22942         return field.name;
22943     });
22944     for(var i = 0, len = o.length; i < len; i++){
22945         p.fields.add(new Ext.data.Field(o[i]));
22946     }
22947     f.getField = function(name){
22948         return p.fields.get(name);
22949     };
22950     return f;
22951 };
22952
22953 Ext.data.Record.PREFIX = 'ext-record';
22954 Ext.data.Record.AUTO_ID = 1;
22955 Ext.data.Record.EDIT = 'edit';
22956 Ext.data.Record.REJECT = 'reject';
22957 Ext.data.Record.COMMIT = 'commit';
22958
22959
22960
22961 Ext.data.Record.id = function(rec) {
22962     rec.phantom = true;
22963     return [Ext.data.Record.PREFIX, '-', Ext.data.Record.AUTO_ID++].join('');
22964 };
22965
22966 Ext.data.Record.prototype = {
22967     
22968     
22969     
22970     
22971     
22972     
22973     dirty : false,
22974     editing : false,
22975     error : null,
22976     
22977     modified : null,
22978     
22979     phantom : false,
22980
22981     
22982     join : function(store){
22983         
22984         this.store = store;
22985     },
22986
22987     
22988     set : function(name, value){
22989         var encode = Ext.isPrimitive(value) ? String : Ext.encode;
22990         if(encode(this.data[name]) == encode(value)) {
22991             return;
22992         }        
22993         this.dirty = true;
22994         if(!this.modified){
22995             this.modified = {};
22996         }
22997         if(this.modified[name] === undefined){
22998             this.modified[name] = this.data[name];
22999         }
23000         this.data[name] = value;
23001         if(!this.editing){
23002             this.afterEdit();
23003         }
23004     },
23005
23006     
23007     afterEdit : function(){
23008         if (this.store != undefined && typeof this.store.afterEdit == "function") {
23009             this.store.afterEdit(this);
23010         }
23011     },
23012
23013     
23014     afterReject : function(){
23015         if(this.store){
23016             this.store.afterReject(this);
23017         }
23018     },
23019
23020     
23021     afterCommit : function(){
23022         if(this.store){
23023             this.store.afterCommit(this);
23024         }
23025     },
23026
23027     
23028     get : function(name){
23029         return this.data[name];
23030     },
23031
23032     
23033     beginEdit : function(){
23034         this.editing = true;
23035         this.modified = this.modified || {};
23036     },
23037
23038     
23039     cancelEdit : function(){
23040         this.editing = false;
23041         delete this.modified;
23042     },
23043
23044     
23045     endEdit : function(){
23046         this.editing = false;
23047         if(this.dirty){
23048             this.afterEdit();
23049         }
23050     },
23051
23052     
23053     reject : function(silent){
23054         var m = this.modified;
23055         for(var n in m){
23056             if(typeof m[n] != "function"){
23057                 this.data[n] = m[n];
23058             }
23059         }
23060         this.dirty = false;
23061         delete this.modified;
23062         this.editing = false;
23063         if(silent !== true){
23064             this.afterReject();
23065         }
23066     },
23067
23068     
23069     commit : function(silent){
23070         this.dirty = false;
23071         delete this.modified;
23072         this.editing = false;
23073         if(silent !== true){
23074             this.afterCommit();
23075         }
23076     },
23077
23078     
23079     getChanges : function(){
23080         var m = this.modified, cs = {};
23081         for(var n in m){
23082             if(m.hasOwnProperty(n)){
23083                 cs[n] = this.data[n];
23084             }
23085         }
23086         return cs;
23087     },
23088
23089     
23090     hasError : function(){
23091         return this.error !== null;
23092     },
23093
23094     
23095     clearError : function(){
23096         this.error = null;
23097     },
23098
23099     
23100     copy : function(newId) {
23101         return new this.constructor(Ext.apply({}, this.data), newId || this.id);
23102     },
23103
23104     
23105     isModified : function(fieldName){
23106         return !!(this.modified && this.modified.hasOwnProperty(fieldName));
23107     },
23108
23109     
23110     isValid : function() {
23111         return this.fields.find(function(f) {
23112             return (f.allowBlank === false && Ext.isEmpty(this.data[f.name])) ? true : false;
23113         },this) ? false : true;
23114     },
23115
23116     
23117     markDirty : function(){
23118         this.dirty = true;
23119         if(!this.modified){
23120             this.modified = {};
23121         }
23122         this.fields.each(function(f) {
23123             this.modified[f.name] = this.data[f.name];
23124         },this);
23125     }
23126 };
23127
23128 Ext.StoreMgr = Ext.apply(new Ext.util.MixedCollection(), {
23129     
23130
23131     
23132     register : function(){
23133         for(var i = 0, s; (s = arguments[i]); i++){
23134             this.add(s);
23135         }
23136     },
23137
23138     
23139     unregister : function(){
23140         for(var i = 0, s; (s = arguments[i]); i++){
23141             this.remove(this.lookup(s));
23142         }
23143     },
23144
23145     
23146     lookup : function(id){
23147         if(Ext.isArray(id)){
23148             var fields = ['field1'], expand = !Ext.isArray(id[0]);
23149             if(!expand){
23150                 for(var i = 2, len = id[0].length; i <= len; ++i){
23151                     fields.push('field' + i);
23152                 }
23153             }
23154             return new Ext.data.ArrayStore({
23155                 fields: fields,
23156                 data: id,
23157                 expandData: expand,
23158                 autoDestroy: true,
23159                 autoCreated: true
23160
23161             });
23162         }
23163         return Ext.isObject(id) ? (id.events ? id : Ext.create(id, 'store')) : this.get(id);
23164     },
23165
23166     
23167     getKey : function(o){
23168          return o.storeId;
23169     }
23170 });
23171 Ext.data.Store = Ext.extend(Ext.util.Observable, {
23172     
23173     
23174     
23175     
23176     
23177     
23178     
23179     writer : undefined,
23180     
23181     
23182     
23183     remoteSort : false,
23184
23185     
23186     autoDestroy : false,
23187
23188     
23189     pruneModifiedRecords : false,
23190
23191     
23192     lastOptions : null,
23193
23194     
23195     autoSave : true,
23196
23197     
23198     batch : true,
23199
23200     
23201     restful: false,
23202
23203     
23204     paramNames : undefined,
23205
23206     
23207     defaultParamNames : {
23208         start : 'start',
23209         limit : 'limit',
23210         sort : 'sort',
23211         dir : 'dir'
23212     },
23213
23214     isDestroyed: false,    
23215     hasMultiSort: false,
23216
23217     
23218     batchKey : '_ext_batch_',
23219
23220     constructor : function(config){
23221         
23222         
23223         
23224         
23225         this.data = new Ext.util.MixedCollection(false);
23226         this.data.getKey = function(o){
23227             return o.id;
23228         };
23229         
23230
23231         
23232         this.removed = [];
23233
23234         if(config && config.data){
23235             this.inlineData = config.data;
23236             delete config.data;
23237         }
23238
23239         Ext.apply(this, config);
23240
23241         
23242         this.baseParams = Ext.isObject(this.baseParams) ? this.baseParams : {};
23243
23244         this.paramNames = Ext.applyIf(this.paramNames || {}, this.defaultParamNames);
23245
23246         if((this.url || this.api) && !this.proxy){
23247             this.proxy = new Ext.data.HttpProxy({url: this.url, api: this.api});
23248         }
23249         
23250         if (this.restful === true && this.proxy) {
23251             
23252             
23253             this.batch = false;
23254             Ext.data.Api.restify(this.proxy);
23255         }
23256
23257         if(this.reader){ 
23258             if(!this.recordType){
23259                 this.recordType = this.reader.recordType;
23260             }
23261             if(this.reader.onMetaChange){
23262                 this.reader.onMetaChange = this.reader.onMetaChange.createSequence(this.onMetaChange, this);
23263             }
23264             if (this.writer) { 
23265                 if (this.writer instanceof(Ext.data.DataWriter) === false) {    
23266                     this.writer = this.buildWriter(this.writer);
23267                 }
23268                 this.writer.meta = this.reader.meta;
23269                 this.pruneModifiedRecords = true;
23270             }
23271         }
23272
23273         
23274
23275         if(this.recordType){
23276             
23277             this.fields = this.recordType.prototype.fields;
23278         }
23279         this.modified = [];
23280
23281         this.addEvents(
23282             
23283             'datachanged',
23284             
23285             'metachange',
23286             
23287             'add',
23288             
23289             'remove',
23290             
23291             'update',
23292             
23293             'clear',
23294             
23295             'exception',
23296             
23297             'beforeload',
23298             
23299             'load',
23300             
23301             'loadexception',
23302             
23303             'beforewrite',
23304             
23305             'write',
23306             
23307             'beforesave',
23308             
23309             'save'
23310
23311         );
23312
23313         if(this.proxy){
23314             
23315             this.relayEvents(this.proxy,  ['loadexception', 'exception']);
23316         }
23317         
23318         if (this.writer) {
23319             this.on({
23320                 scope: this,
23321                 add: this.createRecords,
23322                 remove: this.destroyRecord,
23323                 update: this.updateRecord,
23324                 clear: this.onClear
23325             });
23326         }
23327
23328         this.sortToggle = {};
23329         if(this.sortField){
23330             this.setDefaultSort(this.sortField, this.sortDir);
23331         }else if(this.sortInfo){
23332             this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
23333         }
23334
23335         Ext.data.Store.superclass.constructor.call(this);
23336
23337         if(this.id){
23338             this.storeId = this.id;
23339             delete this.id;
23340         }
23341         if(this.storeId){
23342             Ext.StoreMgr.register(this);
23343         }
23344         if(this.inlineData){
23345             this.loadData(this.inlineData);
23346             delete this.inlineData;
23347         }else if(this.autoLoad){
23348             this.load.defer(10, this, [
23349                 typeof this.autoLoad == 'object' ?
23350                     this.autoLoad : undefined]);
23351         }
23352         
23353         this.batchCounter = 0;
23354         this.batches = {};
23355     },
23356
23357     
23358     buildWriter : function(config) {
23359         var klass = undefined,
23360             type = (config.format || 'json').toLowerCase();
23361         switch (type) {
23362             case 'json':
23363                 klass = Ext.data.JsonWriter;
23364                 break;
23365             case 'xml':
23366                 klass = Ext.data.XmlWriter;
23367                 break;
23368             default:
23369                 klass = Ext.data.JsonWriter;
23370         }
23371         return new klass(config);
23372     },
23373
23374     
23375     destroy : function(){
23376         if(!this.isDestroyed){
23377             if(this.storeId){
23378                 Ext.StoreMgr.unregister(this);
23379             }
23380             this.clearData();
23381             this.data = null;
23382             Ext.destroy(this.proxy);
23383             this.reader = this.writer = null;
23384             this.purgeListeners();
23385             this.isDestroyed = true;
23386         }
23387     },
23388
23389     
23390     add : function(records) {
23391         var i, len, record, index;
23392         
23393         records = [].concat(records);
23394         if (records.length < 1) {
23395             return;
23396         }
23397         
23398         for (i = 0, len = records.length; i < len; i++) {
23399             record = records[i];
23400             
23401             record.join(this);
23402             
23403             if (record.dirty || record.phantom) {
23404                 this.modified.push(record);
23405             }
23406         }
23407         
23408         index = this.data.length;
23409         this.data.addAll(records);
23410         
23411         if (this.snapshot) {
23412             this.snapshot.addAll(records);
23413         }
23414         
23415         this.fireEvent('add', this, records, index);
23416     },
23417
23418     
23419     addSorted : function(record){
23420         var index = this.findInsertIndex(record);
23421         this.insert(index, record);
23422     },
23423     
23424     
23425     doUpdate : function(rec){
23426         this.data.replace(rec.id, rec);
23427         if(this.snapshot){
23428             this.snapshot.replace(rec.id, rec);
23429         }
23430         this.fireEvent('update', this, rec, Ext.data.Record.COMMIT);
23431     },
23432
23433     
23434     remove : function(record){
23435         if(Ext.isArray(record)){
23436             Ext.each(record, function(r){
23437                 this.remove(r);
23438             }, this);
23439             return;
23440         }
23441         var index = this.data.indexOf(record);
23442         if(index > -1){
23443             record.join(null);
23444             this.data.removeAt(index);
23445         }
23446         if(this.pruneModifiedRecords){
23447             this.modified.remove(record);
23448         }
23449         if(this.snapshot){
23450             this.snapshot.remove(record);
23451         }
23452         if(index > -1){
23453             this.fireEvent('remove', this, record, index);
23454         }
23455     },
23456
23457     
23458     removeAt : function(index){
23459         this.remove(this.getAt(index));
23460     },
23461
23462     
23463     removeAll : function(silent){
23464         var items = [];
23465         this.each(function(rec){
23466             items.push(rec);
23467         });
23468         this.clearData();
23469         if(this.snapshot){
23470             this.snapshot.clear();
23471         }
23472         if(this.pruneModifiedRecords){
23473             this.modified = [];
23474         }
23475         if (silent !== true) {  
23476             this.fireEvent('clear', this, items);
23477         }
23478     },
23479
23480     
23481     onClear: function(store, records){
23482         Ext.each(records, function(rec, index){
23483             this.destroyRecord(this, rec, index);
23484         }, this);
23485     },
23486
23487     
23488     insert : function(index, records) {
23489         var i, len, record;
23490         
23491         records = [].concat(records);
23492         for (i = 0, len = records.length; i < len; i++) {
23493             record = records[i];
23494             
23495             this.data.insert(index + i, record);
23496             record.join(this);
23497             
23498             if (record.dirty || record.phantom) {
23499                 this.modified.push(record);
23500             }
23501         }
23502         
23503         if (this.snapshot) {
23504             this.snapshot.addAll(records);
23505         }
23506         
23507         this.fireEvent('add', this, records, index);
23508     },
23509
23510     
23511     indexOf : function(record){
23512         return this.data.indexOf(record);
23513     },
23514
23515     
23516     indexOfId : function(id){
23517         return this.data.indexOfKey(id);
23518     },
23519
23520     
23521     getById : function(id){
23522         return (this.snapshot || this.data).key(id);
23523     },
23524
23525     
23526     getAt : function(index){
23527         return this.data.itemAt(index);
23528     },
23529
23530     
23531     getRange : function(start, end){
23532         return this.data.getRange(start, end);
23533     },
23534
23535     
23536     storeOptions : function(o){
23537         o = Ext.apply({}, o);
23538         delete o.callback;
23539         delete o.scope;
23540         this.lastOptions = o;
23541     },
23542
23543     
23544     clearData: function(){
23545         this.data.each(function(rec) {
23546             rec.join(null);
23547         });
23548         this.data.clear();
23549     },
23550
23551     
23552     load : function(options) {
23553         options = Ext.apply({}, options);
23554         this.storeOptions(options);
23555         if(this.sortInfo && this.remoteSort){
23556             var pn = this.paramNames;
23557             options.params = Ext.apply({}, options.params);
23558             options.params[pn.sort] = this.sortInfo.field;
23559             options.params[pn.dir] = this.sortInfo.direction;
23560         }
23561         try {
23562             return this.execute('read', null, options); 
23563         } catch(e) {
23564             this.handleException(e);
23565             return false;
23566         }
23567     },
23568
23569     
23570     updateRecord : function(store, record, action) {
23571         if (action == Ext.data.Record.EDIT && this.autoSave === true && (!record.phantom || (record.phantom && record.isValid()))) {
23572             this.save();
23573         }
23574     },
23575
23576     
23577     createRecords : function(store, records, index) {
23578         var modified = this.modified,
23579             length   = records.length,
23580             record, i;
23581         
23582         for (i = 0; i < length; i++) {
23583             record = records[i];
23584             
23585             if (record.phantom && record.isValid()) {
23586                 record.markDirty();  
23587                 
23588                 if (modified.indexOf(record) == -1) {
23589                     modified.push(record);
23590                 }
23591             }
23592         }
23593         if (this.autoSave === true) {
23594             this.save();
23595         }
23596     },
23597
23598     
23599     destroyRecord : function(store, record, index) {
23600         if (this.modified.indexOf(record) != -1) {  
23601             this.modified.remove(record);
23602         }
23603         if (!record.phantom) {
23604             this.removed.push(record);
23605
23606             
23607             
23608             
23609             record.lastIndex = index;
23610
23611             if (this.autoSave === true) {
23612                 this.save();
23613             }
23614         }
23615     },
23616
23617     
23618     execute : function(action, rs, options,  batch) {
23619         
23620         if (!Ext.data.Api.isAction(action)) {
23621             throw new Ext.data.Api.Error('execute', action);
23622         }
23623         
23624         options = Ext.applyIf(options||{}, {
23625             params: {}
23626         });
23627         if(batch !== undefined){
23628             this.addToBatch(batch);
23629         }
23630         
23631         
23632         var doRequest = true;
23633
23634         if (action === 'read') {
23635             doRequest = this.fireEvent('beforeload', this, options);
23636             Ext.applyIf(options.params, this.baseParams);
23637         }
23638         else {
23639             
23640             
23641             if (this.writer.listful === true && this.restful !== true) {
23642                 rs = (Ext.isArray(rs)) ? rs : [rs];
23643             }
23644             
23645             else if (Ext.isArray(rs) && rs.length == 1) {
23646                 rs = rs.shift();
23647             }
23648             
23649             if ((doRequest = this.fireEvent('beforewrite', this, action, rs, options)) !== false) {
23650                 this.writer.apply(options.params, this.baseParams, action, rs);
23651             }
23652         }
23653         if (doRequest !== false) {
23654             
23655             if (this.writer && this.proxy.url && !this.proxy.restful && !Ext.data.Api.hasUniqueUrl(this.proxy, action)) {
23656                 options.params.xaction = action;    
23657             }
23658             
23659             
23660             
23661             
23662             
23663             this.proxy.request(Ext.data.Api.actions[action], rs, options.params, this.reader, this.createCallback(action, rs, batch), this, options);
23664         }
23665         return doRequest;
23666     },
23667
23668     
23669     save : function() {
23670         if (!this.writer) {
23671             throw new Ext.data.Store.Error('writer-undefined');
23672         }
23673
23674         var queue = [],
23675             len,
23676             trans,
23677             batch,
23678             data = {},
23679             i;
23680         
23681         if(this.removed.length){
23682             queue.push(['destroy', this.removed]);
23683         }
23684
23685         
23686         var rs = [].concat(this.getModifiedRecords());
23687         if(rs.length){
23688             
23689             var phantoms = [];
23690             for(i = rs.length-1; i >= 0; i--){
23691                 if(rs[i].phantom === true){
23692                     var rec = rs.splice(i, 1).shift();
23693                     if(rec.isValid()){
23694                         phantoms.push(rec);
23695                     }
23696                 }else if(!rs[i].isValid()){ 
23697                     rs.splice(i,1);
23698                 }
23699             }
23700             
23701             if(phantoms.length){
23702                 queue.push(['create', phantoms]);
23703             }
23704
23705             
23706             if(rs.length){
23707                 queue.push(['update', rs]);
23708             }
23709         }
23710         len = queue.length;
23711         if(len){
23712             batch = ++this.batchCounter;
23713             for(i = 0; i < len; ++i){
23714                 trans = queue[i];
23715                 data[trans[0]] = trans[1];
23716             }
23717             if(this.fireEvent('beforesave', this, data) !== false){
23718                 for(i = 0; i < len; ++i){
23719                     trans = queue[i];
23720                     this.doTransaction(trans[0], trans[1], batch);
23721                 }
23722                 return batch;
23723             }
23724         }
23725         return -1;
23726     },
23727
23728     
23729     doTransaction : function(action, rs, batch) {
23730         function transaction(records) {
23731             try{
23732                 this.execute(action, records, undefined, batch);
23733             }catch (e){
23734                 this.handleException(e);
23735             }
23736         }
23737         if(this.batch === false){
23738             for(var i = 0, len = rs.length; i < len; i++){
23739                 transaction.call(this, rs[i]);
23740             }
23741         }else{
23742             transaction.call(this, rs);
23743         }
23744     },
23745
23746     
23747     addToBatch : function(batch){
23748         var b = this.batches,
23749             key = this.batchKey + batch,
23750             o = b[key];
23751
23752         if(!o){
23753             b[key] = o = {
23754                 id: batch,
23755                 count: 0,
23756                 data: {}
23757             };
23758         }
23759         ++o.count;
23760     },
23761
23762     removeFromBatch : function(batch, action, data){
23763         var b = this.batches,
23764             key = this.batchKey + batch,
23765             o = b[key],
23766             arr;
23767
23768
23769         if(o){
23770             arr = o.data[action] || [];
23771             o.data[action] = arr.concat(data);
23772             if(o.count === 1){
23773                 data = o.data;
23774                 delete b[key];
23775                 this.fireEvent('save', this, batch, data);
23776             }else{
23777                 --o.count;
23778             }
23779         }
23780     },
23781
23782     
23783     
23784     createCallback : function(action, rs, batch) {
23785         var actions = Ext.data.Api.actions;
23786         return (action == 'read') ? this.loadRecords : function(data, response, success) {
23787             
23788             this['on' + Ext.util.Format.capitalize(action) + 'Records'](success, rs, [].concat(data));
23789             
23790             if (success === true) {
23791                 this.fireEvent('write', this, action, data, response, rs);
23792             }
23793             this.removeFromBatch(batch, action, data);
23794         };
23795     },
23796
23797     
23798     
23799     
23800     clearModified : function(rs) {
23801         if (Ext.isArray(rs)) {
23802             for (var n=rs.length-1;n>=0;n--) {
23803                 this.modified.splice(this.modified.indexOf(rs[n]), 1);
23804             }
23805         } else {
23806             this.modified.splice(this.modified.indexOf(rs), 1);
23807         }
23808     },
23809
23810     
23811     reMap : function(record) {
23812         if (Ext.isArray(record)) {
23813             for (var i = 0, len = record.length; i < len; i++) {
23814                 this.reMap(record[i]);
23815             }
23816         } else {
23817             delete this.data.map[record._phid];
23818             this.data.map[record.id] = record;
23819             var index = this.data.keys.indexOf(record._phid);
23820             this.data.keys.splice(index, 1, record.id);
23821             delete record._phid;
23822         }
23823     },
23824
23825     
23826     onCreateRecords : function(success, rs, data) {
23827         if (success === true) {
23828             try {
23829                 this.reader.realize(rs, data);
23830                 this.reMap(rs);
23831             }
23832             catch (e) {
23833                 this.handleException(e);
23834                 if (Ext.isArray(rs)) {
23835                     
23836                     this.onCreateRecords(success, rs, data);
23837                 }
23838             }
23839         }
23840     },
23841
23842     
23843     onUpdateRecords : function(success, rs, data) {
23844         if (success === true) {
23845             try {
23846                 this.reader.update(rs, data);
23847             } catch (e) {
23848                 this.handleException(e);
23849                 if (Ext.isArray(rs)) {
23850                     
23851                     this.onUpdateRecords(success, rs, data);
23852                 }
23853             }
23854         }
23855     },
23856
23857     
23858     onDestroyRecords : function(success, rs, data) {
23859         
23860         rs = (rs instanceof Ext.data.Record) ? [rs] : [].concat(rs);
23861         for (var i=0,len=rs.length;i<len;i++) {
23862             this.removed.splice(this.removed.indexOf(rs[i]), 1);
23863         }
23864         if (success === false) {
23865             
23866             
23867             for (i=rs.length-1;i>=0;i--) {
23868                 this.insert(rs[i].lastIndex, rs[i]);    
23869             }
23870         }
23871     },
23872
23873     
23874     handleException : function(e) {
23875         
23876         Ext.handleError(e);
23877     },
23878
23879     
23880     reload : function(options){
23881         this.load(Ext.applyIf(options||{}, this.lastOptions));
23882     },
23883
23884     
23885     
23886     loadRecords : function(o, options, success){
23887         var i, len;
23888         
23889         if (this.isDestroyed === true) {
23890             return;
23891         }
23892         if(!o || success === false){
23893             if(success !== false){
23894                 this.fireEvent('load', this, [], options);
23895             }
23896             if(options.callback){
23897                 options.callback.call(options.scope || this, [], options, false, o);
23898             }
23899             return;
23900         }
23901         var r = o.records, t = o.totalRecords || r.length;
23902         if(!options || options.add !== true){
23903             if(this.pruneModifiedRecords){
23904                 this.modified = [];
23905             }
23906             for(i = 0, len = r.length; i < len; i++){
23907                 r[i].join(this);
23908             }
23909             if(this.snapshot){
23910                 this.data = this.snapshot;
23911                 delete this.snapshot;
23912             }
23913             this.clearData();
23914             this.data.addAll(r);
23915             this.totalLength = t;
23916             this.applySort();
23917             this.fireEvent('datachanged', this);
23918         }else{
23919             var toAdd = [],
23920                 rec,
23921                 cnt = 0;
23922             for(i = 0, len = r.length; i < len; ++i){
23923                 rec = r[i];
23924                 if(this.indexOfId(rec.id) > -1){
23925                     this.doUpdate(rec);
23926                 }else{
23927                     toAdd.push(rec);
23928                     ++cnt;
23929                 }
23930             }
23931             this.totalLength = Math.max(t, this.data.length + cnt);
23932             this.add(toAdd);
23933         }
23934         this.fireEvent('load', this, r, options);
23935         if(options.callback){
23936             options.callback.call(options.scope || this, r, options, true);
23937         }
23938     },
23939
23940     
23941     loadData : function(o, append){
23942         var r = this.reader.readRecords(o);
23943         this.loadRecords(r, {add: append}, true);
23944     },
23945
23946     
23947     getCount : function(){
23948         return this.data.length || 0;
23949     },
23950
23951     
23952     getTotalCount : function(){
23953         return this.totalLength || 0;
23954     },
23955
23956     
23957     getSortState : function(){
23958         return this.sortInfo;
23959     },
23960
23961     
23962     applySort : function(){
23963         if ((this.sortInfo || this.multiSortInfo) && !this.remoteSort) {
23964             this.sortData();
23965         }
23966     },
23967
23968     
23969     sortData : function() {
23970         var sortInfo  = this.hasMultiSort ? this.multiSortInfo : this.sortInfo,
23971             direction = sortInfo.direction || "ASC",
23972             sorters   = sortInfo.sorters,
23973             sortFns   = [];
23974
23975         
23976         if (!this.hasMultiSort) {
23977             sorters = [{direction: direction, field: sortInfo.field}];
23978         }
23979
23980         
23981         for (var i=0, j = sorters.length; i < j; i++) {
23982             sortFns.push(this.createSortFunction(sorters[i].field, sorters[i].direction));
23983         }
23984         
23985         if (sortFns.length == 0) {
23986             return;
23987         }
23988
23989         
23990         
23991         var directionModifier = direction.toUpperCase() == "DESC" ? -1 : 1;
23992
23993         
23994         var fn = function(r1, r2) {
23995           var result = sortFns[0].call(this, r1, r2);
23996
23997           
23998           if (sortFns.length > 1) {
23999               for (var i=1, j = sortFns.length; i < j; i++) {
24000                   result = result || sortFns[i].call(this, r1, r2);
24001               }
24002           }
24003
24004           return directionModifier * result;
24005         };
24006
24007         
24008         this.data.sort(direction, fn);
24009         if (this.snapshot && this.snapshot != this.data) {
24010             this.snapshot.sort(direction, fn);
24011         }
24012     },
24013
24014     
24015     createSortFunction: function(field, direction) {
24016         direction = direction || "ASC";
24017         var directionModifier = direction.toUpperCase() == "DESC" ? -1 : 1;
24018
24019         var sortType = this.fields.get(field).sortType;
24020
24021         
24022         
24023         return function(r1, r2) {
24024             var v1 = sortType(r1.data[field]),
24025                 v2 = sortType(r2.data[field]);
24026
24027             return directionModifier * (v1 > v2 ? 1 : (v1 < v2 ? -1 : 0));
24028         };
24029     },
24030
24031     
24032     setDefaultSort : function(field, dir) {
24033         dir = dir ? dir.toUpperCase() : 'ASC';
24034         this.sortInfo = {field: field, direction: dir};
24035         this.sortToggle[field] = dir;
24036     },
24037
24038     
24039     sort : function(fieldName, dir) {
24040         if (Ext.isArray(arguments[0])) {
24041             return this.multiSort.call(this, fieldName, dir);
24042         } else {
24043             return this.singleSort(fieldName, dir);
24044         }
24045     },
24046
24047     
24048     singleSort: function(fieldName, dir) {
24049         var field = this.fields.get(fieldName);
24050         if (!field) {
24051             return false;
24052         }
24053
24054         var name       = field.name,
24055             sortInfo   = this.sortInfo || null,
24056             sortToggle = this.sortToggle ? this.sortToggle[name] : null;
24057
24058         if (!dir) {
24059             if (sortInfo && sortInfo.field == name) { 
24060                 dir = (this.sortToggle[name] || 'ASC').toggle('ASC', 'DESC');
24061             } else {
24062                 dir = field.sortDir;
24063             }
24064         }
24065
24066         this.sortToggle[name] = dir;
24067         this.sortInfo = {field: name, direction: dir};
24068         this.hasMultiSort = false;
24069
24070         if (this.remoteSort) {
24071             if (!this.load(this.lastOptions)) {
24072                 if (sortToggle) {
24073                     this.sortToggle[name] = sortToggle;
24074                 }
24075                 if (sortInfo) {
24076                     this.sortInfo = sortInfo;
24077                 }
24078             }
24079         } else {
24080             this.applySort();
24081             this.fireEvent('datachanged', this);
24082         }
24083         return true;
24084     },
24085
24086     
24087     multiSort: function(sorters, direction) {
24088         this.hasMultiSort = true;
24089         direction = direction || "ASC";
24090
24091         
24092         if (this.multiSortInfo && direction == this.multiSortInfo.direction) {
24093             direction = direction.toggle("ASC", "DESC");
24094         }
24095
24096         
24097         this.multiSortInfo = {
24098             sorters  : sorters,
24099             direction: direction
24100         };
24101         
24102         if (this.remoteSort) {
24103             this.singleSort(sorters[0].field, sorters[0].direction);
24104
24105         } else {
24106             this.applySort();
24107             this.fireEvent('datachanged', this);
24108         }
24109     },
24110
24111     
24112     each : function(fn, scope){
24113         this.data.each(fn, scope);
24114     },
24115
24116     
24117     getModifiedRecords : function(){
24118         return this.modified;
24119     },
24120
24121     
24122     sum : function(property, start, end){
24123         var rs = this.data.items, v = 0;
24124         start = start || 0;
24125         end = (end || end === 0) ? end : rs.length-1;
24126
24127         for(var i = start; i <= end; i++){
24128             v += (rs[i].data[property] || 0);
24129         }
24130         return v;
24131     },
24132
24133     
24134     createFilterFn : function(property, value, anyMatch, caseSensitive, exactMatch){
24135         if(Ext.isEmpty(value, false)){
24136             return false;
24137         }
24138         value = this.data.createValueMatcher(value, anyMatch, caseSensitive, exactMatch);
24139         return function(r) {
24140             return value.test(r.data[property]);
24141         };
24142     },
24143
24144     
24145     createMultipleFilterFn: function(filters) {
24146         return function(record) {
24147             var isMatch = true;
24148
24149             for (var i=0, j = filters.length; i < j; i++) {
24150                 var filter = filters[i],
24151                     fn     = filter.fn,
24152                     scope  = filter.scope;
24153
24154                 isMatch = isMatch && fn.call(scope, record);
24155             }
24156
24157             return isMatch;
24158         };
24159     },
24160
24161     
24162     filter : function(property, value, anyMatch, caseSensitive, exactMatch){
24163         var fn;
24164         
24165         if (Ext.isObject(property)) {
24166             property = [property];
24167         }
24168
24169         if (Ext.isArray(property)) {
24170             var filters = [];
24171
24172             
24173             for (var i=0, j = property.length; i < j; i++) {
24174                 var filter = property[i],
24175                     func   = filter.fn,
24176                     scope  = filter.scope || this;
24177
24178                 
24179                 if (!Ext.isFunction(func)) {
24180                     func = this.createFilterFn(filter.property, filter.value, filter.anyMatch, filter.caseSensitive, filter.exactMatch);
24181                 }
24182
24183                 filters.push({fn: func, scope: scope});
24184             }
24185
24186             fn = this.createMultipleFilterFn(filters);
24187         } else {
24188             
24189             fn = this.createFilterFn(property, value, anyMatch, caseSensitive, exactMatch);
24190         }
24191
24192         return fn ? this.filterBy(fn) : this.clearFilter();
24193     },
24194
24195     
24196     filterBy : function(fn, scope){
24197         this.snapshot = this.snapshot || this.data;
24198         this.data = this.queryBy(fn, scope || this);
24199         this.fireEvent('datachanged', this);
24200     },
24201
24202     
24203     clearFilter : function(suppressEvent){
24204         if(this.isFiltered()){
24205             this.data = this.snapshot;
24206             delete this.snapshot;
24207             if(suppressEvent !== true){
24208                 this.fireEvent('datachanged', this);
24209             }
24210         }
24211     },
24212
24213     
24214     isFiltered : function(){
24215         return !!this.snapshot && this.snapshot != this.data;
24216     },
24217
24218     
24219     query : function(property, value, anyMatch, caseSensitive){
24220         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
24221         return fn ? this.queryBy(fn) : this.data.clone();
24222     },
24223
24224     
24225     queryBy : function(fn, scope){
24226         var data = this.snapshot || this.data;
24227         return data.filterBy(fn, scope||this);
24228     },
24229
24230     
24231     find : function(property, value, start, anyMatch, caseSensitive){
24232         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
24233         return fn ? this.data.findIndexBy(fn, null, start) : -1;
24234     },
24235
24236     
24237     findExact: function(property, value, start){
24238         return this.data.findIndexBy(function(rec){
24239             return rec.get(property) === value;
24240         }, this, start);
24241     },
24242
24243     
24244     findBy : function(fn, scope, start){
24245         return this.data.findIndexBy(fn, scope, start);
24246     },
24247
24248     
24249     collect : function(dataIndex, allowNull, bypassFilter){
24250         var d = (bypassFilter === true && this.snapshot) ?
24251                 this.snapshot.items : this.data.items;
24252         var v, sv, r = [], l = {};
24253         for(var i = 0, len = d.length; i < len; i++){
24254             v = d[i].data[dataIndex];
24255             sv = String(v);
24256             if((allowNull || !Ext.isEmpty(v)) && !l[sv]){
24257                 l[sv] = true;
24258                 r[r.length] = v;
24259             }
24260         }
24261         return r;
24262     },
24263
24264     
24265     afterEdit : function(record){
24266         if(this.modified.indexOf(record) == -1){
24267             this.modified.push(record);
24268         }
24269         this.fireEvent('update', this, record, Ext.data.Record.EDIT);
24270     },
24271
24272     
24273     afterReject : function(record){
24274         this.modified.remove(record);
24275         this.fireEvent('update', this, record, Ext.data.Record.REJECT);
24276     },
24277
24278     
24279     afterCommit : function(record){
24280         this.modified.remove(record);
24281         this.fireEvent('update', this, record, Ext.data.Record.COMMIT);
24282     },
24283
24284     
24285     commitChanges : function(){
24286         var modified = this.modified.slice(0),
24287             length   = modified.length,
24288             i;
24289             
24290         for (i = 0; i < length; i++){
24291             modified[i].commit();
24292         }
24293         
24294         this.modified = [];
24295         this.removed  = [];
24296     },
24297
24298     
24299     rejectChanges : function() {
24300         var modified = this.modified.slice(0),
24301             removed  = this.removed.slice(0).reverse(),
24302             mLength  = modified.length,
24303             rLength  = removed.length,
24304             i;
24305         
24306         for (i = 0; i < mLength; i++) {
24307             modified[i].reject();
24308         }
24309         
24310         for (i = 0; i < rLength; i++) {
24311             this.insert(removed[i].lastIndex || 0, removed[i]);
24312             removed[i].reject();
24313         }
24314         
24315         this.modified = [];
24316         this.removed  = [];
24317     },
24318
24319     
24320     onMetaChange : function(meta){
24321         this.recordType = this.reader.recordType;
24322         this.fields = this.recordType.prototype.fields;
24323         delete this.snapshot;
24324         if(this.reader.meta.sortInfo){
24325             this.sortInfo = this.reader.meta.sortInfo;
24326         }else if(this.sortInfo  && !this.fields.get(this.sortInfo.field)){
24327             delete this.sortInfo;
24328         }
24329         if(this.writer){
24330             this.writer.meta = this.reader.meta;
24331         }
24332         this.modified = [];
24333         this.fireEvent('metachange', this, this.reader.meta);
24334     },
24335
24336     
24337     findInsertIndex : function(record){
24338         this.suspendEvents();
24339         var data = this.data.clone();
24340         this.data.add(record);
24341         this.applySort();
24342         var index = this.data.indexOf(record);
24343         this.data = data;
24344         this.resumeEvents();
24345         return index;
24346     },
24347
24348     
24349     setBaseParam : function (name, value){
24350         this.baseParams = this.baseParams || {};
24351         this.baseParams[name] = value;
24352     }
24353 });
24354
24355 Ext.reg('store', Ext.data.Store);
24356
24357
24358 Ext.data.Store.Error = Ext.extend(Ext.Error, {
24359     name: 'Ext.data.Store'
24360 });
24361 Ext.apply(Ext.data.Store.Error.prototype, {
24362     lang: {
24363         'writer-undefined' : 'Attempted to execute a write-action without a DataWriter installed.'
24364     }
24365 });
24366
24367 Ext.data.Field = Ext.extend(Object, {
24368     
24369     constructor : function(config){
24370         if(Ext.isString(config)){
24371             config = {name: config};
24372         }
24373         Ext.apply(this, config);
24374         
24375         var types = Ext.data.Types,
24376             st = this.sortType,
24377             t;
24378
24379         if(this.type){
24380             if(Ext.isString(this.type)){
24381                 this.type = Ext.data.Types[this.type.toUpperCase()] || types.AUTO;
24382             }
24383         }else{
24384             this.type = types.AUTO;
24385         }
24386
24387         
24388         if(Ext.isString(st)){
24389             this.sortType = Ext.data.SortTypes[st];
24390         }else if(Ext.isEmpty(st)){
24391             this.sortType = this.type.sortType;
24392         }
24393
24394         if(!this.convert){
24395             this.convert = this.type.convert;
24396         }
24397     },
24398     
24399     
24400     
24401     
24402     
24403     dateFormat: null,
24404     
24405     
24406     useNull: false,
24407     
24408     
24409     defaultValue: "",
24410     
24411     mapping: null,
24412     
24413     sortType : null,
24414     
24415     sortDir : "ASC",
24416     
24417     allowBlank : true
24418 });
24419
24420 Ext.data.DataReader = function(meta, recordType){
24421     
24422     this.meta = meta;
24423     
24424     this.recordType = Ext.isArray(recordType) ?
24425         Ext.data.Record.create(recordType) : recordType;
24426
24427     
24428     if (this.recordType){
24429         this.buildExtractors();
24430     }
24431 };
24432
24433 Ext.data.DataReader.prototype = {
24434     
24435     
24436     getTotal: Ext.emptyFn,
24437     
24438     getRoot: Ext.emptyFn,
24439     
24440     getMessage: Ext.emptyFn,
24441     
24442     getSuccess: Ext.emptyFn,
24443     
24444     getId: Ext.emptyFn,
24445     
24446     buildExtractors : Ext.emptyFn,
24447     
24448     extractValues : Ext.emptyFn,
24449
24450     
24451     realize: function(rs, data){
24452         if (Ext.isArray(rs)) {
24453             for (var i = rs.length - 1; i >= 0; i--) {
24454                 
24455                 if (Ext.isArray(data)) {
24456                     this.realize(rs.splice(i,1).shift(), data.splice(i,1).shift());
24457                 }
24458                 else {
24459                     
24460                     
24461                     this.realize(rs.splice(i,1).shift(), data);
24462                 }
24463             }
24464         }
24465         else {
24466             
24467             if (Ext.isArray(data) && data.length == 1) {
24468                 data = data.shift();
24469             }
24470             if (!this.isData(data)) {
24471                 
24472                 
24473                 throw new Ext.data.DataReader.Error('realize', rs);
24474             }
24475             rs.phantom = false; 
24476             rs._phid = rs.id;  
24477             rs.id = this.getId(data);
24478             rs.data = data;
24479
24480             rs.commit();
24481         }
24482     },
24483
24484     
24485     update : function(rs, data) {
24486         if (Ext.isArray(rs)) {
24487             for (var i=rs.length-1; i >= 0; i--) {
24488                 if (Ext.isArray(data)) {
24489                     this.update(rs.splice(i,1).shift(), data.splice(i,1).shift());
24490                 }
24491                 else {
24492                     
24493                     
24494                     this.update(rs.splice(i,1).shift(), data);
24495                 }
24496             }
24497         }
24498         else {
24499             
24500             if (Ext.isArray(data) && data.length == 1) {
24501                 data = data.shift();
24502             }
24503             if (this.isData(data)) {
24504                 rs.data = Ext.apply(rs.data, data);
24505             }
24506             rs.commit();
24507         }
24508     },
24509
24510     
24511     extractData : function(root, returnRecords) {
24512         
24513         var rawName = (this instanceof Ext.data.JsonReader) ? 'json' : 'node';
24514
24515         var rs = [];
24516
24517         
24518         
24519         if (this.isData(root) && !(this instanceof Ext.data.XmlReader)) {
24520             root = [root];
24521         }
24522         var f       = this.recordType.prototype.fields,
24523             fi      = f.items,
24524             fl      = f.length,
24525             rs      = [];
24526         if (returnRecords === true) {
24527             var Record = this.recordType;
24528             for (var i = 0; i < root.length; i++) {
24529                 var n = root[i];
24530                 var record = new Record(this.extractValues(n, fi, fl), this.getId(n));
24531                 record[rawName] = n;    
24532                 rs.push(record);
24533             }
24534         }
24535         else {
24536             for (var i = 0; i < root.length; i++) {
24537                 var data = this.extractValues(root[i], fi, fl);
24538                 data[this.meta.idProperty] = this.getId(root[i]);
24539                 rs.push(data);
24540             }
24541         }
24542         return rs;
24543     },
24544
24545     
24546     isData : function(data) {
24547         return (data && Ext.isObject(data) && !Ext.isEmpty(this.getId(data))) ? true : false;
24548     },
24549
24550     
24551     onMetaChange : function(meta){
24552         delete this.ef;
24553         this.meta = meta;
24554         this.recordType = Ext.data.Record.create(meta.fields);
24555         this.buildExtractors();
24556     }
24557 };
24558
24559
24560 Ext.data.DataReader.Error = Ext.extend(Ext.Error, {
24561     constructor : function(message, arg) {
24562         this.arg = arg;
24563         Ext.Error.call(this, message);
24564     },
24565     name: 'Ext.data.DataReader'
24566 });
24567 Ext.apply(Ext.data.DataReader.Error.prototype, {
24568     lang : {
24569         'update': "#update received invalid data from server.  Please see docs for DataReader#update and review your DataReader configuration.",
24570         'realize': "#realize was called with invalid remote-data.  Please see the docs for DataReader#realize and review your DataReader configuration.",
24571         'invalid-response': "#readResponse received an invalid response from the server."
24572     }
24573 });
24574
24575 Ext.data.DataWriter = function(config){
24576     Ext.apply(this, config);
24577 };
24578 Ext.data.DataWriter.prototype = {
24579
24580     
24581     writeAllFields : false,
24582     
24583     listful : false,    
24584
24585     
24586     apply : function(params, baseParams, action, rs) {
24587         var data    = [],
24588         renderer    = action + 'Record';
24589         
24590         if (Ext.isArray(rs)) {
24591             Ext.each(rs, function(rec){
24592                 data.push(this[renderer](rec));
24593             }, this);
24594         }
24595         else if (rs instanceof Ext.data.Record) {
24596             data = this[renderer](rs);
24597         }
24598         this.render(params, baseParams, data);
24599     },
24600
24601     
24602     render : Ext.emptyFn,
24603
24604     
24605     updateRecord : Ext.emptyFn,
24606
24607     
24608     createRecord : Ext.emptyFn,
24609
24610     
24611     destroyRecord : Ext.emptyFn,
24612
24613     
24614     toHash : function(rec, config) {
24615         var map = rec.fields.map,
24616             data = {},
24617             raw = (this.writeAllFields === false && rec.phantom === false) ? rec.getChanges() : rec.data,
24618             m;
24619         Ext.iterate(raw, function(prop, value){
24620             if((m = map[prop])){
24621                 data[m.mapping ? m.mapping : m.name] = value;
24622             }
24623         });
24624         
24625         
24626         
24627         if (rec.phantom) {
24628             if (rec.fields.containsKey(this.meta.idProperty) && Ext.isEmpty(rec.data[this.meta.idProperty])) {
24629                 delete data[this.meta.idProperty];
24630             }
24631         } else {
24632             data[this.meta.idProperty] = rec.id;
24633         }
24634         return data;
24635     },
24636
24637     
24638     toArray : function(data) {
24639         var fields = [];
24640         Ext.iterate(data, function(k, v) {fields.push({name: k, value: v});},this);
24641         return fields;
24642     }
24643 };
24644 Ext.data.DataProxy = function(conn){
24645     
24646     
24647     conn = conn || {};
24648
24649     
24650     
24651     
24652
24653     this.api     = conn.api;
24654     this.url     = conn.url;
24655     this.restful = conn.restful;
24656     this.listeners = conn.listeners;
24657
24658     
24659     this.prettyUrls = conn.prettyUrls;
24660
24661     
24662
24663     this.addEvents(
24664         
24665         'exception',
24666         
24667         'beforeload',
24668         
24669         'load',
24670         
24671         'loadexception',
24672         
24673         'beforewrite',
24674         
24675         'write'
24676     );
24677     Ext.data.DataProxy.superclass.constructor.call(this);
24678
24679     
24680     try {
24681         Ext.data.Api.prepare(this);
24682     } catch (e) {
24683         if (e instanceof Ext.data.Api.Error) {
24684             e.toConsole();
24685         }
24686     }
24687     
24688     Ext.data.DataProxy.relayEvents(this, ['beforewrite', 'write', 'exception']);
24689 };
24690
24691 Ext.extend(Ext.data.DataProxy, Ext.util.Observable, {
24692     
24693     restful: false,
24694
24695     
24696     setApi : function() {
24697         if (arguments.length == 1) {
24698             var valid = Ext.data.Api.isValid(arguments[0]);
24699             if (valid === true) {
24700                 this.api = arguments[0];
24701             }
24702             else {
24703                 throw new Ext.data.Api.Error('invalid', valid);
24704             }
24705         }
24706         else if (arguments.length == 2) {
24707             if (!Ext.data.Api.isAction(arguments[0])) {
24708                 throw new Ext.data.Api.Error('invalid', arguments[0]);
24709             }
24710             this.api[arguments[0]] = arguments[1];
24711         }
24712         Ext.data.Api.prepare(this);
24713     },
24714
24715     
24716     isApiAction : function(action) {
24717         return (this.api[action]) ? true : false;
24718     },
24719
24720     
24721     request : function(action, rs, params, reader, callback, scope, options) {
24722         if (!this.api[action] && !this.load) {
24723             throw new Ext.data.DataProxy.Error('action-undefined', action);
24724         }
24725         params = params || {};
24726         if ((action === Ext.data.Api.actions.read) ? this.fireEvent("beforeload", this, params) : this.fireEvent("beforewrite", this, action, rs, params) !== false) {
24727             this.doRequest.apply(this, arguments);
24728         }
24729         else {
24730             callback.call(scope || this, null, options, false);
24731         }
24732     },
24733
24734
24735     
24736     load : null,
24737
24738     
24739     doRequest : function(action, rs, params, reader, callback, scope, options) {
24740         
24741         
24742         
24743         this.load(params, reader, callback, scope, options);
24744     },
24745
24746     
24747     onRead : Ext.emptyFn,
24748     
24749     onWrite : Ext.emptyFn,
24750     
24751     buildUrl : function(action, record) {
24752         record = record || null;
24753
24754         
24755         
24756         
24757         var url = (this.conn && this.conn.url) ? this.conn.url : (this.api[action]) ? this.api[action].url : this.url;
24758         if (!url) {
24759             throw new Ext.data.Api.Error('invalid-url', action);
24760         }
24761
24762         
24763         
24764         
24765         
24766         
24767         
24768         var provides = null;
24769         var m = url.match(/(.*)(\.json|\.xml|\.html)$/);
24770         if (m) {
24771             provides = m[2];    
24772             url      = m[1];    
24773         }
24774         
24775         if ((this.restful === true || this.prettyUrls === true) && record instanceof Ext.data.Record && !record.phantom) {
24776             url += '/' + record.id;
24777         }
24778         return (provides === null) ? url : url + provides;
24779     },
24780
24781     
24782     destroy: function(){
24783         this.purgeListeners();
24784     }
24785 });
24786
24787
24788
24789 Ext.apply(Ext.data.DataProxy, Ext.util.Observable.prototype);
24790 Ext.util.Observable.call(Ext.data.DataProxy);
24791
24792
24793 Ext.data.DataProxy.Error = Ext.extend(Ext.Error, {
24794     constructor : function(message, arg) {
24795         this.arg = arg;
24796         Ext.Error.call(this, message);
24797     },
24798     name: 'Ext.data.DataProxy'
24799 });
24800 Ext.apply(Ext.data.DataProxy.Error.prototype, {
24801     lang: {
24802         'action-undefined': "DataProxy attempted to execute an API-action but found an undefined url / function.  Please review your Proxy url/api-configuration.",
24803         'api-invalid': 'Recieved an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions from Ext.data.Api.actions.'
24804     }
24805 });
24806
24807
24808
24809 Ext.data.Request = function(params) {
24810     Ext.apply(this, params);
24811 };
24812 Ext.data.Request.prototype = {
24813     
24814     action : undefined,
24815     
24816     rs : undefined,
24817     
24818     params: undefined,
24819     
24820     callback : Ext.emptyFn,
24821     
24822     scope : undefined,
24823     
24824     reader : undefined
24825 };
24826
24827 Ext.data.Response = function(params) {
24828     Ext.apply(this, params);
24829 };
24830 Ext.data.Response.prototype = {
24831     
24832     action: undefined,
24833     
24834     success : undefined,
24835     
24836     message : undefined,
24837     
24838     data: undefined,
24839     
24840     raw: undefined,
24841     
24842     records: undefined
24843 };
24844
24845 Ext.data.ScriptTagProxy = function(config){
24846     Ext.apply(this, config);
24847
24848     Ext.data.ScriptTagProxy.superclass.constructor.call(this, config);
24849
24850     this.head = document.getElementsByTagName("head")[0];
24851
24852     
24853 };
24854
24855 Ext.data.ScriptTagProxy.TRANS_ID = 1000;
24856
24857 Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
24858     
24859     
24860     timeout : 30000,
24861     
24862     callbackParam : "callback",
24863     
24864     nocache : true,
24865
24866     
24867     doRequest : function(action, rs, params, reader, callback, scope, arg) {
24868         var p = Ext.urlEncode(Ext.apply(params, this.extraParams));
24869
24870         var url = this.buildUrl(action, rs);
24871         if (!url) {
24872             throw new Ext.data.Api.Error('invalid-url', url);
24873         }
24874         url = Ext.urlAppend(url, p);
24875
24876         if(this.nocache){
24877             url = Ext.urlAppend(url, '_dc=' + (new Date().getTime()));
24878         }
24879         var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
24880         var trans = {
24881             id : transId,
24882             action: action,
24883             cb : "stcCallback"+transId,
24884             scriptId : "stcScript"+transId,
24885             params : params,
24886             arg : arg,
24887             url : url,
24888             callback : callback,
24889             scope : scope,
24890             reader : reader
24891         };
24892         window[trans.cb] = this.createCallback(action, rs, trans);
24893         url += String.format("&{0}={1}", this.callbackParam, trans.cb);
24894         if(this.autoAbort !== false){
24895             this.abort();
24896         }
24897
24898         trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);
24899
24900         var script = document.createElement("script");
24901         script.setAttribute("src", url);
24902         script.setAttribute("type", "text/javascript");
24903         script.setAttribute("id", trans.scriptId);
24904         this.head.appendChild(script);
24905
24906         this.trans = trans;
24907     },
24908
24909     
24910     createCallback : function(action, rs, trans) {
24911         var self = this;
24912         return function(res) {
24913             self.trans = false;
24914             self.destroyTrans(trans, true);
24915             if (action === Ext.data.Api.actions.read) {
24916                 self.onRead.call(self, action, trans, res);
24917             } else {
24918                 self.onWrite.call(self, action, trans, res, rs);
24919             }
24920         };
24921     },
24922     
24923     onRead : function(action, trans, res) {
24924         var result;
24925         try {
24926             result = trans.reader.readRecords(res);
24927         }catch(e){
24928             
24929             this.fireEvent("loadexception", this, trans, res, e);
24930
24931             this.fireEvent('exception', this, 'response', action, trans, res, e);
24932             trans.callback.call(trans.scope||window, null, trans.arg, false);
24933             return;
24934         }
24935         if (result.success === false) {
24936             
24937             this.fireEvent('loadexception', this, trans, res);
24938
24939             this.fireEvent('exception', this, 'remote', action, trans, res, null);
24940         } else {
24941             this.fireEvent("load", this, res, trans.arg);
24942         }
24943         trans.callback.call(trans.scope||window, result, trans.arg, result.success);
24944     },
24945     
24946     onWrite : function(action, trans, response, rs) {
24947         var reader = trans.reader;
24948         try {
24949             
24950             var res = reader.readResponse(action, response);
24951         } catch (e) {
24952             this.fireEvent('exception', this, 'response', action, trans, res, e);
24953             trans.callback.call(trans.scope||window, null, res, false);
24954             return;
24955         }
24956         if(!res.success === true){
24957             this.fireEvent('exception', this, 'remote', action, trans, res, rs);
24958             trans.callback.call(trans.scope||window, null, res, false);
24959             return;
24960         }
24961         this.fireEvent("write", this, action, res.data, res, rs, trans.arg );
24962         trans.callback.call(trans.scope||window, res.data, res, true);
24963     },
24964
24965     
24966     isLoading : function(){
24967         return this.trans ? true : false;
24968     },
24969
24970     
24971     abort : function(){
24972         if(this.isLoading()){
24973             this.destroyTrans(this.trans);
24974         }
24975     },
24976
24977     
24978     destroyTrans : function(trans, isLoaded){
24979         this.head.removeChild(document.getElementById(trans.scriptId));
24980         clearTimeout(trans.timeoutId);
24981         if(isLoaded){
24982             window[trans.cb] = undefined;
24983             try{
24984                 delete window[trans.cb];
24985             }catch(e){}
24986         }else{
24987             
24988             window[trans.cb] = function(){
24989                 window[trans.cb] = undefined;
24990                 try{
24991                     delete window[trans.cb];
24992                 }catch(e){}
24993             };
24994         }
24995     },
24996
24997     
24998     handleFailure : function(trans){
24999         this.trans = false;
25000         this.destroyTrans(trans, false);
25001         if (trans.action === Ext.data.Api.actions.read) {
25002             
25003             this.fireEvent("loadexception", this, null, trans.arg);
25004         }
25005
25006         this.fireEvent('exception', this, 'response', trans.action, {
25007             response: null,
25008             options: trans.arg
25009         });
25010         trans.callback.call(trans.scope||window, null, trans.arg, false);
25011     },
25012
25013     
25014     destroy: function(){
25015         this.abort();
25016         Ext.data.ScriptTagProxy.superclass.destroy.call(this);
25017     }
25018 });
25019 Ext.data.HttpProxy = function(conn){
25020     Ext.data.HttpProxy.superclass.constructor.call(this, conn);
25021
25022     
25023     this.conn = conn;
25024
25025     
25026     
25027     
25028     
25029     this.conn.url = null;
25030
25031     this.useAjax = !conn || !conn.events;
25032
25033     
25034     var actions = Ext.data.Api.actions;
25035     this.activeRequest = {};
25036     for (var verb in actions) {
25037         this.activeRequest[actions[verb]] = undefined;
25038     }
25039 };
25040
25041 Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
25042     
25043     getConnection : function() {
25044         return this.useAjax ? Ext.Ajax : this.conn;
25045     },
25046
25047     
25048     setUrl : function(url, makePermanent) {
25049         this.conn.url = url;
25050         if (makePermanent === true) {
25051             this.url = url;
25052             this.api = null;
25053             Ext.data.Api.prepare(this);
25054         }
25055     },
25056
25057     
25058     doRequest : function(action, rs, params, reader, cb, scope, arg) {
25059         var  o = {
25060             method: (this.api[action]) ? this.api[action]['method'] : undefined,
25061             request: {
25062                 callback : cb,
25063                 scope : scope,
25064                 arg : arg
25065             },
25066             reader: reader,
25067             callback : this.createCallback(action, rs),
25068             scope: this
25069         };
25070
25071         
25072         
25073         if (params.jsonData) {
25074             o.jsonData = params.jsonData;
25075         } else if (params.xmlData) {
25076             o.xmlData = params.xmlData;
25077         } else {
25078             o.params = params || {};
25079         }
25080         
25081         
25082         
25083         this.conn.url = this.buildUrl(action, rs);
25084
25085         if(this.useAjax){
25086
25087             Ext.applyIf(o, this.conn);
25088
25089             
25090             if (this.activeRequest[action]) {
25091                 
25092                 
25093                 
25094                 
25095                 
25096             }
25097             this.activeRequest[action] = Ext.Ajax.request(o);
25098         }else{
25099             this.conn.request(o);
25100         }
25101         
25102         this.conn.url = null;
25103     },
25104
25105     
25106     createCallback : function(action, rs) {
25107         return function(o, success, response) {
25108             this.activeRequest[action] = undefined;
25109             if (!success) {
25110                 if (action === Ext.data.Api.actions.read) {
25111                     
25112                     
25113                     this.fireEvent('loadexception', this, o, response);
25114                 }
25115                 this.fireEvent('exception', this, 'response', action, o, response);
25116                 o.request.callback.call(o.request.scope, null, o.request.arg, false);
25117                 return;
25118             }
25119             if (action === Ext.data.Api.actions.read) {
25120                 this.onRead(action, o, response);
25121             } else {
25122                 this.onWrite(action, o, response, rs);
25123             }
25124         };
25125     },
25126
25127     
25128     onRead : function(action, o, response) {
25129         var result;
25130         try {
25131             result = o.reader.read(response);
25132         }catch(e){
25133             
25134             
25135             this.fireEvent('loadexception', this, o, response, e);
25136
25137             this.fireEvent('exception', this, 'response', action, o, response, e);
25138             o.request.callback.call(o.request.scope, null, o.request.arg, false);
25139             return;
25140         }
25141         if (result.success === false) {
25142             
25143             
25144             this.fireEvent('loadexception', this, o, response);
25145
25146             
25147             var res = o.reader.readResponse(action, response);
25148             this.fireEvent('exception', this, 'remote', action, o, res, null);
25149         }
25150         else {
25151             this.fireEvent('load', this, o, o.request.arg);
25152         }
25153         
25154         
25155         
25156         o.request.callback.call(o.request.scope, result, o.request.arg, result.success);
25157     },
25158     
25159     onWrite : function(action, o, response, rs) {
25160         var reader = o.reader;
25161         var res;
25162         try {
25163             res = reader.readResponse(action, response);
25164         } catch (e) {
25165             this.fireEvent('exception', this, 'response', action, o, response, e);
25166             o.request.callback.call(o.request.scope, null, o.request.arg, false);
25167             return;
25168         }
25169         if (res.success === true) {
25170             this.fireEvent('write', this, action, res.data, res, rs, o.request.arg);
25171         } else {
25172             this.fireEvent('exception', this, 'remote', action, o, res, rs);
25173         }
25174         
25175         
25176         
25177         o.request.callback.call(o.request.scope, res.data, res, res.success);
25178     },
25179
25180     
25181     destroy: function(){
25182         if(!this.useAjax){
25183             this.conn.abort();
25184         }else if(this.activeRequest){
25185             var actions = Ext.data.Api.actions;
25186             for (var verb in actions) {
25187                 if(this.activeRequest[actions[verb]]){
25188                     Ext.Ajax.abort(this.activeRequest[actions[verb]]);
25189                 }
25190             }
25191         }
25192         Ext.data.HttpProxy.superclass.destroy.call(this);
25193     }
25194 });
25195 Ext.data.MemoryProxy = function(data){
25196     
25197     var api = {};
25198     api[Ext.data.Api.actions.read] = true;
25199     Ext.data.MemoryProxy.superclass.constructor.call(this, {
25200         api: api
25201     });
25202     this.data = data;
25203 };
25204
25205 Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {
25206     
25207
25208        
25209     doRequest : function(action, rs, params, reader, callback, scope, arg) {
25210         
25211         params = params || {};
25212         var result;
25213         try {
25214             result = reader.readRecords(this.data);
25215         }catch(e){
25216             
25217             this.fireEvent("loadexception", this, null, arg, e);
25218
25219             this.fireEvent('exception', this, 'response', action, arg, null, e);
25220             callback.call(scope, null, arg, false);
25221             return;
25222         }
25223         callback.call(scope, result, arg, true);
25224     }
25225 });
25226 Ext.data.Types = new function(){
25227     var st = Ext.data.SortTypes;
25228     Ext.apply(this, {
25229         
25230         stripRe: /[\$,%]/g,
25231         
25232         
25233         AUTO: {
25234             convert: function(v){ return v; },
25235             sortType: st.none,
25236             type: 'auto'
25237         },
25238
25239         
25240         STRING: {
25241             convert: function(v){ return (v === undefined || v === null) ? '' : String(v); },
25242             sortType: st.asUCString,
25243             type: 'string'
25244         },
25245
25246         
25247         INT: {
25248             convert: function(v){
25249                 return v !== undefined && v !== null && v !== '' ?
25250                     parseInt(String(v).replace(Ext.data.Types.stripRe, ''), 10) : (this.useNull ? null : 0);
25251             },
25252             sortType: st.none,
25253             type: 'int'
25254         },
25255         
25256         
25257         FLOAT: {
25258             convert: function(v){
25259                 return v !== undefined && v !== null && v !== '' ?
25260                     parseFloat(String(v).replace(Ext.data.Types.stripRe, ''), 10) : (this.useNull ? null : 0);
25261             },
25262             sortType: st.none,
25263             type: 'float'
25264         },
25265         
25266         
25267         BOOL: {
25268             convert: function(v){ return v === true || v === 'true' || v == 1; },
25269             sortType: st.none,
25270             type: 'bool'
25271         },
25272         
25273         
25274         DATE: {
25275             convert: function(v){
25276                 var df = this.dateFormat;
25277                 if(!v){
25278                     return null;
25279                 }
25280                 if(Ext.isDate(v)){
25281                     return v;
25282                 }
25283                 if(df){
25284                     if(df == 'timestamp'){
25285                         return new Date(v*1000);
25286                     }
25287                     if(df == 'time'){
25288                         return new Date(parseInt(v, 10));
25289                     }
25290                     return Date.parseDate(v, df);
25291                 }
25292                 var parsed = Date.parse(v);
25293                 return parsed ? new Date(parsed) : null;
25294             },
25295             sortType: st.asDate,
25296             type: 'date'
25297         }
25298     });
25299     
25300     Ext.apply(this, {
25301         
25302         BOOLEAN: this.BOOL,
25303         
25304         INTEGER: this.INT,
25305         
25306         NUMBER: this.FLOAT    
25307     });
25308 };
25309 Ext.data.JsonWriter = Ext.extend(Ext.data.DataWriter, {
25310     
25311     encode : true,
25312     
25313     encodeDelete: false,
25314     
25315     constructor : function(config){
25316         Ext.data.JsonWriter.superclass.constructor.call(this, config);    
25317     },
25318
25319     
25320     render : function(params, baseParams, data) {
25321         if (this.encode === true) {
25322             
25323             Ext.apply(params, baseParams);
25324             params[this.meta.root] = Ext.encode(data);
25325         } else {
25326             
25327             var jdata = Ext.apply({}, baseParams);
25328             jdata[this.meta.root] = data;
25329             params.jsonData = jdata;
25330         }
25331     },
25332     
25333     createRecord : function(rec) {
25334        return this.toHash(rec);
25335     },
25336     
25337     updateRecord : function(rec) {
25338         return this.toHash(rec);
25339
25340     },
25341     
25342     destroyRecord : function(rec){
25343         if(this.encodeDelete){
25344             var data = {};
25345             data[this.meta.idProperty] = rec.id;
25346             return data;
25347         }else{
25348             return rec.id;
25349         }
25350     }
25351 });
25352 Ext.data.JsonReader = function(meta, recordType){
25353     meta = meta || {};
25354     
25355     
25356     
25357     
25358     Ext.applyIf(meta, {
25359         idProperty: 'id',
25360         successProperty: 'success',
25361         totalProperty: 'total'
25362     });
25363
25364     Ext.data.JsonReader.superclass.constructor.call(this, meta, recordType || meta.fields);
25365 };
25366 Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {
25367     
25368     
25369     read : function(response){
25370         var json = response.responseText;
25371         var o = Ext.decode(json);
25372         if(!o) {
25373             throw {message: 'JsonReader.read: Json object not found'};
25374         }
25375         return this.readRecords(o);
25376     },
25377
25378     
25379     
25380     readResponse : function(action, response) {
25381         var o = (response.responseText !== undefined) ? Ext.decode(response.responseText) : response;
25382         if(!o) {
25383             throw new Ext.data.JsonReader.Error('response');
25384         }
25385
25386         var root = this.getRoot(o);
25387         if (action === Ext.data.Api.actions.create) {
25388             var def = Ext.isDefined(root);
25389             if (def && Ext.isEmpty(root)) {
25390                 throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
25391             }
25392             else if (!def) {
25393                 throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
25394             }
25395         }
25396
25397         
25398         var res = new Ext.data.Response({
25399             action: action,
25400             success: this.getSuccess(o),
25401             data: (root) ? this.extractData(root, false) : [],
25402             message: this.getMessage(o),
25403             raw: o
25404         });
25405
25406         
25407         if (Ext.isEmpty(res.success)) {
25408             throw new Ext.data.JsonReader.Error('successProperty-response', this.meta.successProperty);
25409         }
25410         return res;
25411     },
25412
25413     
25414     readRecords : function(o){
25415         
25416         this.jsonData = o;
25417         if(o.metaData){
25418             this.onMetaChange(o.metaData);
25419         }
25420         var s = this.meta, Record = this.recordType,
25421             f = Record.prototype.fields, fi = f.items, fl = f.length, v;
25422
25423         var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;
25424         if(s.totalProperty){
25425             v = parseInt(this.getTotal(o), 10);
25426             if(!isNaN(v)){
25427                 totalRecords = v;
25428             }
25429         }
25430         if(s.successProperty){
25431             v = this.getSuccess(o);
25432             if(v === false || v === 'false'){
25433                 success = false;
25434             }
25435         }
25436
25437         
25438         return {
25439             success : success,
25440             records : this.extractData(root, true), 
25441             totalRecords : totalRecords
25442         };
25443     },
25444
25445     
25446     buildExtractors : function() {
25447         if(this.ef){
25448             return;
25449         }
25450         var s = this.meta, Record = this.recordType,
25451             f = Record.prototype.fields, fi = f.items, fl = f.length;
25452
25453         if(s.totalProperty) {
25454             this.getTotal = this.createAccessor(s.totalProperty);
25455         }
25456         if(s.successProperty) {
25457             this.getSuccess = this.createAccessor(s.successProperty);
25458         }
25459         if (s.messageProperty) {
25460             this.getMessage = this.createAccessor(s.messageProperty);
25461         }
25462         this.getRoot = s.root ? this.createAccessor(s.root) : function(p){return p;};
25463         if (s.id || s.idProperty) {
25464             var g = this.createAccessor(s.id || s.idProperty);
25465             this.getId = function(rec) {
25466                 var r = g(rec);
25467                 return (r === undefined || r === '') ? null : r;
25468             };
25469         } else {
25470             this.getId = function(){return null;};
25471         }
25472         var ef = [];
25473         for(var i = 0; i < fl; i++){
25474             f = fi[i];
25475             var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
25476             ef.push(this.createAccessor(map));
25477         }
25478         this.ef = ef;
25479     },
25480
25481     
25482     simpleAccess : function(obj, subsc) {
25483         return obj[subsc];
25484     },
25485
25486     
25487     createAccessor : function(){
25488         var re = /[\[\.]/;
25489         return function(expr) {
25490             if(Ext.isEmpty(expr)){
25491                 return Ext.emptyFn;
25492             }
25493             if(Ext.isFunction(expr)){
25494                 return expr;
25495             }
25496             var i = String(expr).search(re);
25497             if(i >= 0){
25498                 return new Function('obj', 'return obj' + (i > 0 ? '.' : '') + expr);
25499             }
25500             return function(obj){
25501                 return obj[expr];
25502             };
25503
25504         };
25505     }(),
25506
25507     
25508     extractValues : function(data, items, len) {
25509         var f, values = {};
25510         for(var j = 0; j < len; j++){
25511             f = items[j];
25512             var v = this.ef[j](data);
25513             values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data);
25514         }
25515         return values;
25516     }
25517 });
25518
25519
25520 Ext.data.JsonReader.Error = Ext.extend(Ext.Error, {
25521     constructor : function(message, arg) {
25522         this.arg = arg;
25523         Ext.Error.call(this, message);
25524     },
25525     name : 'Ext.data.JsonReader'
25526 });
25527 Ext.apply(Ext.data.JsonReader.Error.prototype, {
25528     lang: {
25529         'response': 'An error occurred while json-decoding your server response',
25530         'successProperty-response': 'Could not locate your "successProperty" in your server response.  Please review your JsonReader config to ensure the config-property "successProperty" matches the property in your server-response.  See the JsonReader docs.',
25531         'root-undefined-config': 'Your JsonReader was configured without a "root" property.  Please review your JsonReader config and make sure to define the root property.  See the JsonReader docs.',
25532         'idProperty-undefined' : 'Your JsonReader was configured without an "idProperty"  Please review your JsonReader configuration and ensure the "idProperty" is set (e.g.: "id").  See the JsonReader docs.',
25533         'root-empty': 'Data was expected to be returned by the server in the "root" property of the response.  Please review your JsonReader configuration to ensure the "root" property matches that returned in the server-response.  See JsonReader docs.'
25534     }
25535 });
25536
25537 Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {
25538     
25539     
25540     
25541     
25542     readRecords : function(o){
25543         this.arrayData = o;
25544         var s = this.meta,
25545             sid = s ? Ext.num(s.idIndex, s.id) : null,
25546             recordType = this.recordType,
25547             fields = recordType.prototype.fields,
25548             records = [],
25549             success = true,
25550             v;
25551
25552         var root = this.getRoot(o);
25553
25554         for(var i = 0, len = root.length; i < len; i++) {
25555             var n = root[i],
25556                 values = {},
25557                 id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
25558             for(var j = 0, jlen = fields.length; j < jlen; j++) {
25559                 var f = fields.items[j],
25560                     k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
25561                 v = n[k] !== undefined ? n[k] : f.defaultValue;
25562                 v = f.convert(v, n);
25563                 values[f.name] = v;
25564             }
25565             var record = new recordType(values, id);
25566             record.json = n;
25567             records[records.length] = record;
25568         }
25569
25570         var totalRecords = records.length;
25571
25572         if(s.totalProperty) {
25573             v = parseInt(this.getTotal(o), 10);
25574             if(!isNaN(v)) {
25575                 totalRecords = v;
25576             }
25577         }
25578         if(s.successProperty){
25579             v = this.getSuccess(o);
25580             if(v === false || v === 'false'){
25581                 success = false;
25582             }
25583         }
25584
25585         return {
25586             success : success,
25587             records : records,
25588             totalRecords : totalRecords
25589         };
25590     }
25591 });
25592 Ext.data.ArrayStore = Ext.extend(Ext.data.Store, {
25593     
25594     constructor: function(config){
25595         Ext.data.ArrayStore.superclass.constructor.call(this, Ext.apply(config, {
25596             reader: new Ext.data.ArrayReader(config)
25597         }));
25598     },
25599
25600     loadData : function(data, append){
25601         if(this.expandData === true){
25602             var r = [];
25603             for(var i = 0, len = data.length; i < len; i++){
25604                 r[r.length] = [data[i]];
25605             }
25606             data = r;
25607         }
25608         Ext.data.ArrayStore.superclass.loadData.call(this, data, append);
25609     }
25610 });
25611 Ext.reg('arraystore', Ext.data.ArrayStore);
25612
25613
25614 Ext.data.SimpleStore = Ext.data.ArrayStore;
25615 Ext.reg('simplestore', Ext.data.SimpleStore);
25616 Ext.data.JsonStore = Ext.extend(Ext.data.Store, {
25617     
25618     constructor: function(config){
25619         Ext.data.JsonStore.superclass.constructor.call(this, Ext.apply(config, {
25620             reader: new Ext.data.JsonReader(config)
25621         }));
25622     }
25623 });
25624 Ext.reg('jsonstore', Ext.data.JsonStore);
25625 Ext.data.XmlWriter = function(params) {
25626     Ext.data.XmlWriter.superclass.constructor.apply(this, arguments);
25627     
25628     this.tpl = (typeof(this.tpl) === 'string') ? new Ext.XTemplate(this.tpl).compile() : this.tpl.compile();
25629 };
25630 Ext.extend(Ext.data.XmlWriter, Ext.data.DataWriter, {
25631     
25632     documentRoot: 'xrequest',
25633     
25634     forceDocumentRoot: false,
25635     
25636     root: 'records',
25637     
25638     xmlVersion : '1.0',
25639     
25640     xmlEncoding: 'ISO-8859-15',
25641     
25642     
25643     tpl: '<tpl for="."><\u003fxml version="{version}" encoding="{encoding}"\u003f><tpl if="documentRoot"><{documentRoot}><tpl for="baseParams"><tpl for="."><{name}>{value}</{name}></tpl></tpl></tpl><tpl if="records.length&gt;1"><{root}></tpl><tpl for="records"><{parent.record}><tpl for="."><{name}>{value}</{name}></tpl></{parent.record}></tpl><tpl if="records.length&gt;1"></{root}></tpl><tpl if="documentRoot"></{documentRoot}></tpl></tpl>',
25644
25645
25646     
25647     render : function(params, baseParams, data) {
25648         baseParams = this.toArray(baseParams);
25649         params.xmlData = this.tpl.applyTemplate({
25650             version: this.xmlVersion,
25651             encoding: this.xmlEncoding,
25652             documentRoot: (baseParams.length > 0 || this.forceDocumentRoot === true) ? this.documentRoot : false,
25653             record: this.meta.record,
25654             root: this.root,
25655             baseParams: baseParams,
25656             records: (Ext.isArray(data[0])) ? data : [data]
25657         });
25658     },
25659
25660     
25661     createRecord : function(rec) {
25662         return this.toArray(this.toHash(rec));
25663     },
25664
25665     
25666     updateRecord : function(rec) {
25667         return this.toArray(this.toHash(rec));
25668
25669     },
25670     
25671     destroyRecord : function(rec) {
25672         var data = {};
25673         data[this.meta.idProperty] = rec.id;
25674         return this.toArray(data);
25675     }
25676 });
25677
25678 Ext.data.XmlReader = function(meta, recordType){
25679     meta = meta || {};
25680
25681     
25682     Ext.applyIf(meta, {
25683         idProperty: meta.idProperty || meta.idPath || meta.id,
25684         successProperty: meta.successProperty || meta.success
25685     });
25686
25687     Ext.data.XmlReader.superclass.constructor.call(this, meta, recordType || meta.fields);
25688 };
25689 Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {
25690     
25691     read : function(response){
25692         var doc = response.responseXML;
25693         if(!doc) {
25694             throw {message: "XmlReader.read: XML Document not available"};
25695         }
25696         return this.readRecords(doc);
25697     },
25698
25699     
25700     readRecords : function(doc){
25701         
25702         this.xmlData = doc;
25703
25704         var root    = doc.documentElement || doc,
25705             q       = Ext.DomQuery,
25706             totalRecords = 0,
25707             success = true;
25708
25709         if(this.meta.totalProperty){
25710             totalRecords = this.getTotal(root, 0);
25711         }
25712         if(this.meta.successProperty){
25713             success = this.getSuccess(root);
25714         }
25715
25716         var records = this.extractData(q.select(this.meta.record, root), true); 
25717
25718         
25719         return {
25720             success : success,
25721             records : records,
25722             totalRecords : totalRecords || records.length
25723         };
25724     },
25725
25726     
25727     readResponse : function(action, response) {
25728         var q = Ext.DomQuery,
25729             doc = response.responseXML,
25730             root = doc.documentElement || doc;
25731
25732         
25733         var res = new Ext.data.Response({
25734             action: action,
25735             success : this.getSuccess(root),
25736             message: this.getMessage(root),
25737             data: this.extractData(q.select(this.meta.record, root) || q.select(this.meta.root, root), false),
25738             raw: doc
25739         });
25740
25741         if (Ext.isEmpty(res.success)) {
25742             throw new Ext.data.DataReader.Error('successProperty-response', this.meta.successProperty);
25743         }
25744
25745         
25746         if (action === Ext.data.Api.actions.create) {
25747             var def = Ext.isDefined(res.data);
25748             if (def && Ext.isEmpty(res.data)) {
25749                 throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
25750             }
25751             else if (!def) {
25752                 throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
25753             }
25754         }
25755         return res;
25756     },
25757
25758     getSuccess : function() {
25759         return true;
25760     },
25761
25762     
25763     buildExtractors : function() {
25764         if(this.ef){
25765             return;
25766         }
25767         var s       = this.meta,
25768             Record  = this.recordType,
25769             f       = Record.prototype.fields,
25770             fi      = f.items,
25771             fl      = f.length;
25772
25773         if(s.totalProperty) {
25774             this.getTotal = this.createAccessor(s.totalProperty);
25775         }
25776         if(s.successProperty) {
25777             this.getSuccess = this.createAccessor(s.successProperty);
25778         }
25779         if (s.messageProperty) {
25780             this.getMessage = this.createAccessor(s.messageProperty);
25781         }
25782         this.getRoot = function(res) {
25783             return (!Ext.isEmpty(res[this.meta.record])) ? res[this.meta.record] : res[this.meta.root];
25784         };
25785         if (s.idPath || s.idProperty) {
25786             var g = this.createAccessor(s.idPath || s.idProperty);
25787             this.getId = function(rec) {
25788                 var id = g(rec) || rec.id;
25789                 return (id === undefined || id === '') ? null : id;
25790             };
25791         } else {
25792             this.getId = function(){return null;};
25793         }
25794         var ef = [];
25795         for(var i = 0; i < fl; i++){
25796             f = fi[i];
25797             var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
25798             ef.push(this.createAccessor(map));
25799         }
25800         this.ef = ef;
25801     },
25802
25803     
25804     createAccessor : function(){
25805         var q = Ext.DomQuery;
25806         return function(key) {
25807             if (Ext.isFunction(key)) {
25808                 return key;
25809             }
25810             switch(key) {
25811                 case this.meta.totalProperty:
25812                     return function(root, def){
25813                         return q.selectNumber(key, root, def);
25814                     };
25815                     break;
25816                 case this.meta.successProperty:
25817                     return function(root, def) {
25818                         var sv = q.selectValue(key, root, true);
25819                         var success = sv !== false && sv !== 'false';
25820                         return success;
25821                     };
25822                     break;
25823                 default:
25824                     return function(root, def) {
25825                         return q.selectValue(key, root, def);
25826                     };
25827                     break;
25828             }
25829         };
25830     }(),
25831
25832     
25833     extractValues : function(data, items, len) {
25834         var f, values = {};
25835         for(var j = 0; j < len; j++){
25836             f = items[j];
25837             var v = this.ef[j](data);
25838             values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data);
25839         }
25840         return values;
25841     }
25842 });
25843 Ext.data.XmlStore = Ext.extend(Ext.data.Store, {
25844     
25845     constructor: function(config){
25846         Ext.data.XmlStore.superclass.constructor.call(this, Ext.apply(config, {
25847             reader: new Ext.data.XmlReader(config)
25848         }));
25849     }
25850 });
25851 Ext.reg('xmlstore', Ext.data.XmlStore);
25852 Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {
25853
25854     
25855     constructor: function(config) {
25856         config = config || {};
25857
25858         
25859         
25860         
25861         
25862         this.hasMultiSort  = true;
25863         this.multiSortInfo = this.multiSortInfo || {sorters: []};
25864
25865         var sorters    = this.multiSortInfo.sorters,
25866             groupField = config.groupField || this.groupField,
25867             sortInfo   = config.sortInfo || this.sortInfo,
25868             groupDir   = config.groupDir || this.groupDir;
25869
25870         
25871         if(groupField){
25872             sorters.push({
25873                 field    : groupField,
25874                 direction: groupDir
25875             });
25876         }
25877
25878         
25879         if (sortInfo) {
25880             sorters.push(sortInfo);
25881         }
25882
25883         Ext.data.GroupingStore.superclass.constructor.call(this, config);
25884
25885         this.addEvents(
25886           
25887           'groupchange'
25888         );
25889
25890         this.applyGroupField();
25891     },
25892
25893     
25894     
25895     remoteGroup : false,
25896     
25897     groupOnSort:false,
25898
25899     
25900     groupDir : 'ASC',
25901
25902     
25903     clearGrouping : function(){
25904         this.groupField = false;
25905
25906         if(this.remoteGroup){
25907             if(this.baseParams){
25908                 delete this.baseParams.groupBy;
25909                 delete this.baseParams.groupDir;
25910             }
25911             var lo = this.lastOptions;
25912             if(lo && lo.params){
25913                 delete lo.params.groupBy;
25914                 delete lo.params.groupDir;
25915             }
25916
25917             this.reload();
25918         }else{
25919             this.sort();
25920             this.fireEvent('datachanged', this);
25921         }
25922     },
25923
25924     
25925     groupBy : function(field, forceRegroup, direction) {
25926         direction = direction ? (String(direction).toUpperCase() == 'DESC' ? 'DESC' : 'ASC') : this.groupDir;
25927
25928         if (this.groupField == field && this.groupDir == direction && !forceRegroup) {
25929             return; 
25930         }
25931
25932         
25933         
25934         var sorters = this.multiSortInfo.sorters;
25935         if (sorters.length > 0 && sorters[0].field == this.groupField) {
25936             sorters.shift();
25937         }
25938
25939         this.groupField = field;
25940         this.groupDir = direction;
25941         this.applyGroupField();
25942
25943         var fireGroupEvent = function() {
25944             this.fireEvent('groupchange', this, this.getGroupState());
25945         };
25946
25947         if (this.groupOnSort) {
25948             this.sort(field, direction);
25949             fireGroupEvent.call(this);
25950             return;
25951         }
25952
25953         if (this.remoteGroup) {
25954             this.on('load', fireGroupEvent, this, {single: true});
25955             this.reload();
25956         } else {
25957             this.sort(sorters);
25958             fireGroupEvent.call(this);
25959         }
25960     },
25961
25962     
25963     
25964     sort : function(fieldName, dir) {
25965         if (this.remoteSort) {
25966             return Ext.data.GroupingStore.superclass.sort.call(this, fieldName, dir);
25967         }
25968
25969         var sorters = [];
25970
25971         
25972         if (Ext.isArray(arguments[0])) {
25973             sorters = arguments[0];
25974         } else if (fieldName == undefined) {
25975             
25976             
25977             sorters = this.sortInfo ? [this.sortInfo] : [];
25978         } else {
25979             
25980             
25981             var field = this.fields.get(fieldName);
25982             if (!field) return false;
25983
25984             var name       = field.name,
25985                 sortInfo   = this.sortInfo || null,
25986                 sortToggle = this.sortToggle ? this.sortToggle[name] : null;
25987
25988             if (!dir) {
25989                 if (sortInfo && sortInfo.field == name) { 
25990                     dir = (this.sortToggle[name] || 'ASC').toggle('ASC', 'DESC');
25991                 } else {
25992                     dir = field.sortDir;
25993                 }
25994             }
25995
25996             this.sortToggle[name] = dir;
25997             this.sortInfo = {field: name, direction: dir};
25998
25999             sorters = [this.sortInfo];
26000         }
26001
26002         
26003         if (this.groupField) {
26004             sorters.unshift({direction: this.groupDir, field: this.groupField});
26005         }
26006
26007         return this.multiSort.call(this, sorters, dir);
26008     },
26009
26010     
26011     applyGroupField: function(){
26012         if (this.remoteGroup) {
26013             if(!this.baseParams){
26014                 this.baseParams = {};
26015             }
26016
26017             Ext.apply(this.baseParams, {
26018                 groupBy : this.groupField,
26019                 groupDir: this.groupDir
26020             });
26021
26022             var lo = this.lastOptions;
26023             if (lo && lo.params) {
26024                 lo.params.groupDir = this.groupDir;
26025
26026                 
26027                 delete lo.params.groupBy;
26028             }
26029         }
26030     },
26031
26032     
26033     applyGrouping : function(alwaysFireChange){
26034         if(this.groupField !== false){
26035             this.groupBy(this.groupField, true, this.groupDir);
26036             return true;
26037         }else{
26038             if(alwaysFireChange === true){
26039                 this.fireEvent('datachanged', this);
26040             }
26041             return false;
26042         }
26043     },
26044
26045     
26046     getGroupState : function(){
26047         return this.groupOnSort && this.groupField !== false ?
26048                (this.sortInfo ? this.sortInfo.field : undefined) : this.groupField;
26049     }
26050 });
26051 Ext.reg('groupingstore', Ext.data.GroupingStore);
26052
26053 Ext.data.DirectProxy = function(config){
26054     Ext.apply(this, config);
26055     if(typeof this.paramOrder == 'string'){
26056         this.paramOrder = this.paramOrder.split(/[\s,|]/);
26057     }
26058     Ext.data.DirectProxy.superclass.constructor.call(this, config);
26059 };
26060
26061 Ext.extend(Ext.data.DirectProxy, Ext.data.DataProxy, {
26062     
26063     paramOrder: undefined,
26064
26065     
26066     paramsAsHash: true,
26067
26068     
26069     directFn : undefined,
26070
26071     
26072     doRequest : function(action, rs, params, reader, callback, scope, options) {
26073         var args = [],
26074             directFn = this.api[action] || this.directFn;
26075
26076         switch (action) {
26077             case Ext.data.Api.actions.create:
26078                 args.push(params.jsonData);             
26079                 break;
26080             case Ext.data.Api.actions.read:
26081                 
26082                 if(directFn.directCfg.method.len > 0){
26083                     if(this.paramOrder){
26084                         for(var i = 0, len = this.paramOrder.length; i < len; i++){
26085                             args.push(params[this.paramOrder[i]]);
26086                         }
26087                     }else if(this.paramsAsHash){
26088                         args.push(params);
26089                     }
26090                 }
26091                 break;
26092             case Ext.data.Api.actions.update:
26093                 args.push(params.jsonData);        
26094                 break;
26095             case Ext.data.Api.actions.destroy:
26096                 args.push(params.jsonData);        
26097                 break;
26098         }
26099
26100         var trans = {
26101             params : params || {},
26102             request: {
26103                 callback : callback,
26104                 scope : scope,
26105                 arg : options
26106             },
26107             reader: reader
26108         };
26109
26110         args.push(this.createCallback(action, rs, trans), this);
26111         directFn.apply(window, args);
26112     },
26113
26114     
26115     createCallback : function(action, rs, trans) {
26116         var me = this;
26117         return function(result, res) {
26118             if (!res.status) {
26119                 
26120                 if (action === Ext.data.Api.actions.read) {
26121                     me.fireEvent("loadexception", me, trans, res, null);
26122                 }
26123                 me.fireEvent('exception', me, 'remote', action, trans, res, null);
26124                 trans.request.callback.call(trans.request.scope, null, trans.request.arg, false);
26125                 return;
26126             }
26127             if (action === Ext.data.Api.actions.read) {
26128                 me.onRead(action, trans, result, res);
26129             } else {
26130                 me.onWrite(action, trans, result, res, rs);
26131             }
26132         };
26133     },
26134
26135     
26136     onRead : function(action, trans, result, res) {
26137         var records;
26138         try {
26139             records = trans.reader.readRecords(result);
26140         }
26141         catch (ex) {
26142             
26143             this.fireEvent("loadexception", this, trans, res, ex);
26144
26145             this.fireEvent('exception', this, 'response', action, trans, res, ex);
26146             trans.request.callback.call(trans.request.scope, null, trans.request.arg, false);
26147             return;
26148         }
26149         this.fireEvent("load", this, res, trans.request.arg);
26150         trans.request.callback.call(trans.request.scope, records, trans.request.arg, true);
26151     },
26152     
26153     onWrite : function(action, trans, result, res, rs) {
26154         var data = trans.reader.extractData(trans.reader.getRoot(result), false);
26155         var success = trans.reader.getSuccess(result);
26156         success = (success !== false);
26157         if (success){
26158             this.fireEvent("write", this, action, data, res, rs, trans.request.arg);
26159         }else{
26160             this.fireEvent('exception', this, 'remote', action, trans, result, rs);
26161         }
26162         trans.request.callback.call(trans.request.scope, data, res, success);
26163     }
26164 });
26165
26166 Ext.data.DirectStore = Ext.extend(Ext.data.Store, {
26167     constructor : function(config){
26168         
26169         var c = Ext.apply({}, {
26170             batchTransactions: false
26171         }, config);
26172         Ext.data.DirectStore.superclass.constructor.call(this, Ext.apply(c, {
26173             proxy: Ext.isDefined(c.proxy) ? c.proxy : new Ext.data.DirectProxy(Ext.copyTo({}, c, 'paramOrder,paramsAsHash,directFn,api')),
26174             reader: (!Ext.isDefined(c.reader) && c.fields) ? new Ext.data.JsonReader(Ext.copyTo({}, c, 'totalProperty,root,idProperty'), c.fields) : c.reader
26175         }));
26176     }
26177 });
26178 Ext.reg('directstore', Ext.data.DirectStore);
26179
26180 Ext.Direct = Ext.extend(Ext.util.Observable, {
26181     
26182
26183     
26184     exceptions: {
26185         TRANSPORT: 'xhr',
26186         PARSE: 'parse',
26187         LOGIN: 'login',
26188         SERVER: 'exception'
26189     },
26190
26191     
26192     constructor: function(){
26193         this.addEvents(
26194             
26195             'event',
26196             
26197             'exception'
26198         );
26199         this.transactions = {};
26200         this.providers = {};
26201     },
26202
26203     
26204     addProvider : function(provider){
26205         var a = arguments;
26206         if(a.length > 1){
26207             for(var i = 0, len = a.length; i < len; i++){
26208                 this.addProvider(a[i]);
26209             }
26210             return;
26211         }
26212
26213         
26214         if(!provider.events){
26215             provider = new Ext.Direct.PROVIDERS[provider.type](provider);
26216         }
26217         provider.id = provider.id || Ext.id();
26218         this.providers[provider.id] = provider;
26219
26220         provider.on('data', this.onProviderData, this);
26221         provider.on('exception', this.onProviderException, this);
26222
26223
26224         if(!provider.isConnected()){
26225             provider.connect();
26226         }
26227
26228         return provider;
26229     },
26230
26231     
26232     getProvider : function(id){
26233         return this.providers[id];
26234     },
26235
26236     removeProvider : function(id){
26237         var provider = id.id ? id : this.providers[id];
26238         provider.un('data', this.onProviderData, this);
26239         provider.un('exception', this.onProviderException, this);
26240         delete this.providers[provider.id];
26241         return provider;
26242     },
26243
26244     addTransaction: function(t){
26245         this.transactions[t.tid] = t;
26246         return t;
26247     },
26248
26249     removeTransaction: function(t){
26250         delete this.transactions[t.tid || t];
26251         return t;
26252     },
26253
26254     getTransaction: function(tid){
26255         return this.transactions[tid.tid || tid];
26256     },
26257
26258     onProviderData : function(provider, e){
26259         if(Ext.isArray(e)){
26260             for(var i = 0, len = e.length; i < len; i++){
26261                 this.onProviderData(provider, e[i]);
26262             }
26263             return;
26264         }
26265         if(e.name && e.name != 'event' && e.name != 'exception'){
26266             this.fireEvent(e.name, e);
26267         }else if(e.type == 'exception'){
26268             this.fireEvent('exception', e);
26269         }
26270         this.fireEvent('event', e, provider);
26271     },
26272
26273     createEvent : function(response, extraProps){
26274         return new Ext.Direct.eventTypes[response.type](Ext.apply(response, extraProps));
26275     }
26276 });
26277
26278 Ext.Direct = new Ext.Direct();
26279
26280 Ext.Direct.TID = 1;
26281 Ext.Direct.PROVIDERS = {};
26282 Ext.Direct.Transaction = function(config){
26283     Ext.apply(this, config);
26284     this.tid = ++Ext.Direct.TID;
26285     this.retryCount = 0;
26286 };
26287 Ext.Direct.Transaction.prototype = {
26288     send: function(){
26289         this.provider.queueTransaction(this);
26290     },
26291
26292     retry: function(){
26293         this.retryCount++;
26294         this.send();
26295     },
26296
26297     getProvider: function(){
26298         return this.provider;
26299     }
26300 };Ext.Direct.Event = function(config){
26301     Ext.apply(this, config);
26302 };
26303
26304 Ext.Direct.Event.prototype = {
26305     status: true,
26306     getData: function(){
26307         return this.data;
26308     }
26309 };
26310
26311 Ext.Direct.RemotingEvent = Ext.extend(Ext.Direct.Event, {
26312     type: 'rpc',
26313     getTransaction: function(){
26314         return this.transaction || Ext.Direct.getTransaction(this.tid);
26315     }
26316 });
26317
26318 Ext.Direct.ExceptionEvent = Ext.extend(Ext.Direct.RemotingEvent, {
26319     status: false,
26320     type: 'exception'
26321 });
26322
26323 Ext.Direct.eventTypes = {
26324     'rpc':  Ext.Direct.RemotingEvent,
26325     'event':  Ext.Direct.Event,
26326     'exception':  Ext.Direct.ExceptionEvent
26327 };
26328
26329 Ext.direct.Provider = Ext.extend(Ext.util.Observable, {    
26330     
26331         
26332         
26333     priority: 1,
26334
26335         
26336  
26337     
26338     constructor : function(config){
26339         Ext.apply(this, config);
26340         this.addEvents(
26341                         
26342             'connect',
26343                         
26344             'disconnect',
26345                         
26346             'data',
26347                                     
26348             'exception'
26349         );
26350         Ext.direct.Provider.superclass.constructor.call(this, config);
26351     },
26352
26353     
26354     isConnected: function(){
26355         return false;
26356     },
26357
26358     
26359     connect: Ext.emptyFn,
26360     
26361     
26362     disconnect: Ext.emptyFn
26363 });
26364
26365 Ext.direct.JsonProvider = Ext.extend(Ext.direct.Provider, {
26366     parseResponse: function(xhr){
26367         if(!Ext.isEmpty(xhr.responseText)){
26368             if(typeof xhr.responseText == 'object'){
26369                 return xhr.responseText;
26370             }
26371             return Ext.decode(xhr.responseText);
26372         }
26373         return null;
26374     },
26375
26376     getEvents: function(xhr){
26377         var data = null;
26378         try{
26379             data = this.parseResponse(xhr);
26380         }catch(e){
26381             var event = new Ext.Direct.ExceptionEvent({
26382                 data: e,
26383                 xhr: xhr,
26384                 code: Ext.Direct.exceptions.PARSE,
26385                 message: 'Error parsing json response: \n\n ' + data
26386             });
26387             return [event];
26388         }
26389         var events = [];
26390         if(Ext.isArray(data)){
26391             for(var i = 0, len = data.length; i < len; i++){
26392                 events.push(Ext.Direct.createEvent(data[i]));
26393             }
26394         }else{
26395             events.push(Ext.Direct.createEvent(data));
26396         }
26397         return events;
26398     }
26399 });
26400 Ext.direct.PollingProvider = Ext.extend(Ext.direct.JsonProvider, {
26401     
26402     
26403     priority: 3,
26404     
26405     
26406     interval: 3000,
26407
26408     
26409     
26410     
26411
26412     
26413     constructor : function(config){
26414         Ext.direct.PollingProvider.superclass.constructor.call(this, config);
26415         this.addEvents(
26416             
26417             'beforepoll',            
26418             
26419             'poll'
26420         );
26421     },
26422
26423     
26424     isConnected: function(){
26425         return !!this.pollTask;
26426     },
26427
26428     
26429     connect: function(){
26430         if(this.url && !this.pollTask){
26431             this.pollTask = Ext.TaskMgr.start({
26432                 run: function(){
26433                     if(this.fireEvent('beforepoll', this) !== false){
26434                         if(typeof this.url == 'function'){
26435                             this.url(this.baseParams);
26436                         }else{
26437                             Ext.Ajax.request({
26438                                 url: this.url,
26439                                 callback: this.onData,
26440                                 scope: this,
26441                                 params: this.baseParams
26442                             });
26443                         }
26444                     }
26445                 },
26446                 interval: this.interval,
26447                 scope: this
26448             });
26449             this.fireEvent('connect', this);
26450         }else if(!this.url){
26451             throw 'Error initializing PollingProvider, no url configured.';
26452         }
26453     },
26454
26455     
26456     disconnect: function(){
26457         if(this.pollTask){
26458             Ext.TaskMgr.stop(this.pollTask);
26459             delete this.pollTask;
26460             this.fireEvent('disconnect', this);
26461         }
26462     },
26463
26464     
26465     onData: function(opt, success, xhr){
26466         if(success){
26467             var events = this.getEvents(xhr);
26468             for(var i = 0, len = events.length; i < len; i++){
26469                 var e = events[i];
26470                 this.fireEvent('data', this, e);
26471             }
26472         }else{
26473             var e = new Ext.Direct.ExceptionEvent({
26474                 data: e,
26475                 code: Ext.Direct.exceptions.TRANSPORT,
26476                 message: 'Unable to connect to the server.',
26477                 xhr: xhr
26478             });
26479             this.fireEvent('data', this, e);
26480         }
26481     }
26482 });
26483
26484 Ext.Direct.PROVIDERS['polling'] = Ext.direct.PollingProvider;
26485 Ext.direct.RemotingProvider = Ext.extend(Ext.direct.JsonProvider, {       
26486     
26487     
26488     
26489     
26490     
26491     
26492     
26493     
26494     
26495     enableBuffer: 10,
26496     
26497     
26498     maxRetries: 1,
26499     
26500     
26501     timeout: undefined,
26502
26503     constructor : function(config){
26504         Ext.direct.RemotingProvider.superclass.constructor.call(this, config);
26505         this.addEvents(
26506                         
26507             'beforecall',            
26508                         
26509             'call'
26510         );
26511         this.namespace = (Ext.isString(this.namespace)) ? Ext.ns(this.namespace) : this.namespace || window;
26512         this.transactions = {};
26513         this.callBuffer = [];
26514     },
26515
26516     
26517     initAPI : function(){
26518         var o = this.actions;
26519         for(var c in o){
26520             var cls = this.namespace[c] || (this.namespace[c] = {}),
26521                 ms = o[c];
26522             for(var i = 0, len = ms.length; i < len; i++){
26523                 var m = ms[i];
26524                 cls[m.name] = this.createMethod(c, m);
26525             }
26526         }
26527     },
26528
26529     
26530     isConnected: function(){
26531         return !!this.connected;
26532     },
26533
26534     connect: function(){
26535         if(this.url){
26536             this.initAPI();
26537             this.connected = true;
26538             this.fireEvent('connect', this);
26539         }else if(!this.url){
26540             throw 'Error initializing RemotingProvider, no url configured.';
26541         }
26542     },
26543
26544     disconnect: function(){
26545         if(this.connected){
26546             this.connected = false;
26547             this.fireEvent('disconnect', this);
26548         }
26549     },
26550
26551     onData: function(opt, success, xhr){
26552         if(success){
26553             var events = this.getEvents(xhr);
26554             for(var i = 0, len = events.length; i < len; i++){
26555                 var e = events[i],
26556                     t = this.getTransaction(e);
26557                 this.fireEvent('data', this, e);
26558                 if(t){
26559                     this.doCallback(t, e, true);
26560                     Ext.Direct.removeTransaction(t);
26561                 }
26562             }
26563         }else{
26564             var ts = [].concat(opt.ts);
26565             for(var i = 0, len = ts.length; i < len; i++){
26566                 var t = this.getTransaction(ts[i]);
26567                 if(t && t.retryCount < this.maxRetries){
26568                     t.retry();
26569                 }else{
26570                     var e = new Ext.Direct.ExceptionEvent({
26571                         data: e,
26572                         transaction: t,
26573                         code: Ext.Direct.exceptions.TRANSPORT,
26574                         message: 'Unable to connect to the server.',
26575                         xhr: xhr
26576                     });
26577                     this.fireEvent('data', this, e);
26578                     if(t){
26579                         this.doCallback(t, e, false);
26580                         Ext.Direct.removeTransaction(t);
26581                     }
26582                 }
26583             }
26584         }
26585     },
26586
26587     getCallData: function(t){
26588         return {
26589             action: t.action,
26590             method: t.method,
26591             data: t.data,
26592             type: 'rpc',
26593             tid: t.tid
26594         };
26595     },
26596
26597     doSend : function(data){
26598         var o = {
26599             url: this.url,
26600             callback: this.onData,
26601             scope: this,
26602             ts: data,
26603             timeout: this.timeout
26604         }, callData;
26605
26606         if(Ext.isArray(data)){
26607             callData = [];
26608             for(var i = 0, len = data.length; i < len; i++){
26609                 callData.push(this.getCallData(data[i]));
26610             }
26611         }else{
26612             callData = this.getCallData(data);
26613         }
26614
26615         if(this.enableUrlEncode){
26616             var params = {};
26617             params[Ext.isString(this.enableUrlEncode) ? this.enableUrlEncode : 'data'] = Ext.encode(callData);
26618             o.params = params;
26619         }else{
26620             o.jsonData = callData;
26621         }
26622         Ext.Ajax.request(o);
26623     },
26624
26625     combineAndSend : function(){
26626         var len = this.callBuffer.length;
26627         if(len > 0){
26628             this.doSend(len == 1 ? this.callBuffer[0] : this.callBuffer);
26629             this.callBuffer = [];
26630         }
26631     },
26632
26633     queueTransaction: function(t){
26634         if(t.form){
26635             this.processForm(t);
26636             return;
26637         }
26638         this.callBuffer.push(t);
26639         if(this.enableBuffer){
26640             if(!this.callTask){
26641                 this.callTask = new Ext.util.DelayedTask(this.combineAndSend, this);
26642             }
26643             this.callTask.delay(Ext.isNumber(this.enableBuffer) ? this.enableBuffer : 10);
26644         }else{
26645             this.combineAndSend();
26646         }
26647     },
26648
26649     doCall : function(c, m, args){
26650         var data = null, hs = args[m.len], scope = args[m.len+1];
26651
26652         if(m.len !== 0){
26653             data = args.slice(0, m.len);
26654         }
26655
26656         var t = new Ext.Direct.Transaction({
26657             provider: this,
26658             args: args,
26659             action: c,
26660             method: m.name,
26661             data: data,
26662             cb: scope && Ext.isFunction(hs) ? hs.createDelegate(scope) : hs
26663         });
26664
26665         if(this.fireEvent('beforecall', this, t, m) !== false){
26666             Ext.Direct.addTransaction(t);
26667             this.queueTransaction(t);
26668             this.fireEvent('call', this, t, m);
26669         }
26670     },
26671
26672     doForm : function(c, m, form, callback, scope){
26673         var t = new Ext.Direct.Transaction({
26674             provider: this,
26675             action: c,
26676             method: m.name,
26677             args:[form, callback, scope],
26678             cb: scope && Ext.isFunction(callback) ? callback.createDelegate(scope) : callback,
26679             isForm: true
26680         });
26681
26682         if(this.fireEvent('beforecall', this, t, m) !== false){
26683             Ext.Direct.addTransaction(t);
26684             var isUpload = String(form.getAttribute("enctype")).toLowerCase() == 'multipart/form-data',
26685                 params = {
26686                     extTID: t.tid,
26687                     extAction: c,
26688                     extMethod: m.name,
26689                     extType: 'rpc',
26690                     extUpload: String(isUpload)
26691                 };
26692             
26693             
26694             
26695             Ext.apply(t, {
26696                 form: Ext.getDom(form),
26697                 isUpload: isUpload,
26698                 params: callback && Ext.isObject(callback.params) ? Ext.apply(params, callback.params) : params
26699             });
26700             this.fireEvent('call', this, t, m);
26701             this.processForm(t);
26702         }
26703     },
26704     
26705     processForm: function(t){
26706         Ext.Ajax.request({
26707             url: this.url,
26708             params: t.params,
26709             callback: this.onData,
26710             scope: this,
26711             form: t.form,
26712             isUpload: t.isUpload,
26713             ts: t
26714         });
26715     },
26716
26717     createMethod : function(c, m){
26718         var f;
26719         if(!m.formHandler){
26720             f = function(){
26721                 this.doCall(c, m, Array.prototype.slice.call(arguments, 0));
26722             }.createDelegate(this);
26723         }else{
26724             f = function(form, callback, scope){
26725                 this.doForm(c, m, form, callback, scope);
26726             }.createDelegate(this);
26727         }
26728         f.directCfg = {
26729             action: c,
26730             method: m
26731         };
26732         return f;
26733     },
26734
26735     getTransaction: function(opt){
26736         return opt && opt.tid ? Ext.Direct.getTransaction(opt.tid) : null;
26737     },
26738
26739     doCallback: function(t, e){
26740         var fn = e.status ? 'success' : 'failure';
26741         if(t && t.cb){
26742             var hs = t.cb,
26743                 result = Ext.isDefined(e.result) ? e.result : e.data;
26744             if(Ext.isFunction(hs)){
26745                 hs(result, e);
26746             } else{
26747                 Ext.callback(hs[fn], hs.scope, [result, e]);
26748                 Ext.callback(hs.callback, hs.scope, [result, e]);
26749             }
26750         }
26751     }
26752 });
26753 Ext.Direct.PROVIDERS['remoting'] = Ext.direct.RemotingProvider;
26754 Ext.Resizable = Ext.extend(Ext.util.Observable, {
26755
26756     constructor: function(el, config){
26757         this.el = Ext.get(el);
26758         if(config && config.wrap){
26759             config.resizeChild = this.el;
26760             this.el = this.el.wrap(typeof config.wrap == 'object' ? config.wrap : {cls:'xresizable-wrap'});
26761             this.el.id = this.el.dom.id = config.resizeChild.id + '-rzwrap';
26762             this.el.setStyle('overflow', 'hidden');
26763             this.el.setPositioning(config.resizeChild.getPositioning());
26764             config.resizeChild.clearPositioning();
26765             if(!config.width || !config.height){
26766                 var csize = config.resizeChild.getSize();
26767                 this.el.setSize(csize.width, csize.height);
26768             }
26769             if(config.pinned && !config.adjustments){
26770                 config.adjustments = 'auto';
26771             }
26772         }
26773
26774         
26775         this.proxy = this.el.createProxy({tag: 'div', cls: 'x-resizable-proxy', id: this.el.id + '-rzproxy'}, Ext.getBody());
26776         this.proxy.unselectable();
26777         this.proxy.enableDisplayMode('block');
26778
26779         Ext.apply(this, config);
26780
26781         if(this.pinned){
26782             this.disableTrackOver = true;
26783             this.el.addClass('x-resizable-pinned');
26784         }
26785         
26786         var position = this.el.getStyle('position');
26787         if(position != 'absolute' && position != 'fixed'){
26788             this.el.setStyle('position', 'relative');
26789         }
26790         if(!this.handles){ 
26791             this.handles = 's,e,se';
26792             if(this.multiDirectional){
26793                 this.handles += ',n,w';
26794             }
26795         }
26796         if(this.handles == 'all'){
26797             this.handles = 'n s e w ne nw se sw';
26798         }
26799         var hs = this.handles.split(/\s*?[,;]\s*?| /);
26800         var ps = Ext.Resizable.positions;
26801         for(var i = 0, len = hs.length; i < len; i++){
26802             if(hs[i] && ps[hs[i]]){
26803                 var pos = ps[hs[i]];
26804                 this[pos] = new Ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent, this.handleCls);
26805             }
26806         }
26807         
26808         this.corner = this.southeast;
26809
26810         if(this.handles.indexOf('n') != -1 || this.handles.indexOf('w') != -1){
26811             this.updateBox = true;
26812         }
26813
26814         this.activeHandle = null;
26815
26816         if(this.resizeChild){
26817             if(typeof this.resizeChild == 'boolean'){
26818                 this.resizeChild = Ext.get(this.el.dom.firstChild, true);
26819             }else{
26820                 this.resizeChild = Ext.get(this.resizeChild, true);
26821             }
26822         }
26823
26824         if(this.adjustments == 'auto'){
26825             var rc = this.resizeChild;
26826             var hw = this.west, he = this.east, hn = this.north, hs = this.south;
26827             if(rc && (hw || hn)){
26828                 rc.position('relative');
26829                 rc.setLeft(hw ? hw.el.getWidth() : 0);
26830                 rc.setTop(hn ? hn.el.getHeight() : 0);
26831             }
26832             this.adjustments = [
26833                 (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),
26834                 (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1
26835             ];
26836         }
26837
26838         if(this.draggable){
26839             this.dd = this.dynamic ?
26840                 this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});
26841             this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);
26842             if(this.constrainTo){
26843                 this.dd.constrainTo(this.constrainTo);
26844             }
26845         }
26846
26847         this.addEvents(
26848             
26849             'beforeresize',
26850             
26851             'resize'
26852         );
26853
26854         if(this.width !== null && this.height !== null){
26855             this.resizeTo(this.width, this.height);
26856         }else{
26857             this.updateChildSize();
26858         }
26859         if(Ext.isIE){
26860             this.el.dom.style.zoom = 1;
26861         }
26862         Ext.Resizable.superclass.constructor.call(this);
26863     },
26864
26865     
26866     adjustments : [0, 0],
26867     
26868     animate : false,
26869     
26870     
26871     disableTrackOver : false,
26872     
26873     draggable: false,
26874     
26875     duration : 0.35,
26876     
26877     dynamic : false,
26878     
26879     easing : 'easeOutStrong',
26880     
26881     enabled : true,
26882     
26883     
26884     handles : false,
26885     
26886     multiDirectional : false,
26887     
26888     height : null,
26889     
26890     width : null,
26891     
26892     heightIncrement : 0,
26893     
26894     widthIncrement : 0,
26895     
26896     minHeight : 5,
26897     
26898     minWidth : 5,
26899     
26900     maxHeight : 10000,
26901     
26902     maxWidth : 10000,
26903     
26904     minX: 0,
26905     
26906     minY: 0,
26907     
26908     pinned : false,
26909     
26910     preserveRatio : false,
26911     
26912     resizeChild : false,
26913     
26914     transparent: false,
26915     
26916     
26917     
26918
26919
26920     
26921     resizeTo : function(width, height){
26922         this.el.setSize(width, height);
26923         this.updateChildSize();
26924         this.fireEvent('resize', this, width, height, null);
26925     },
26926
26927     
26928     startSizing : function(e, handle){
26929         this.fireEvent('beforeresize', this, e);
26930         if(this.enabled){ 
26931
26932             if(!this.overlay){
26933                 this.overlay = this.el.createProxy({tag: 'div', cls: 'x-resizable-overlay', html: '&#160;'}, Ext.getBody());
26934                 this.overlay.unselectable();
26935                 this.overlay.enableDisplayMode('block');
26936                 this.overlay.on({
26937                     scope: this,
26938                     mousemove: this.onMouseMove,
26939                     mouseup: this.onMouseUp
26940                 });
26941             }
26942             this.overlay.setStyle('cursor', handle.el.getStyle('cursor'));
26943
26944             this.resizing = true;
26945             this.startBox = this.el.getBox();
26946             this.startPoint = e.getXY();
26947             this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],
26948                             (this.startBox.y + this.startBox.height) - this.startPoint[1]];
26949
26950             this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
26951             this.overlay.show();
26952
26953             if(this.constrainTo) {
26954                 var ct = Ext.get(this.constrainTo);
26955                 this.resizeRegion = ct.getRegion().adjust(
26956                     ct.getFrameWidth('t'),
26957                     ct.getFrameWidth('l'),
26958                     -ct.getFrameWidth('b'),
26959                     -ct.getFrameWidth('r')
26960                 );
26961             }
26962
26963             this.proxy.setStyle('visibility', 'hidden'); 
26964             this.proxy.show();
26965             this.proxy.setBox(this.startBox);
26966             if(!this.dynamic){
26967                 this.proxy.setStyle('visibility', 'visible');
26968             }
26969         }
26970     },
26971
26972     
26973     onMouseDown : function(handle, e){
26974         if(this.enabled){
26975             e.stopEvent();
26976             this.activeHandle = handle;
26977             this.startSizing(e, handle);
26978         }
26979     },
26980
26981     
26982     onMouseUp : function(e){
26983         this.activeHandle = null;
26984         var size = this.resizeElement();
26985         this.resizing = false;
26986         this.handleOut();
26987         this.overlay.hide();
26988         this.proxy.hide();
26989         this.fireEvent('resize', this, size.width, size.height, e);
26990     },
26991
26992     
26993     updateChildSize : function(){
26994         if(this.resizeChild){
26995             var el = this.el;
26996             var child = this.resizeChild;
26997             var adj = this.adjustments;
26998             if(el.dom.offsetWidth){
26999                 var b = el.getSize(true);
27000                 child.setSize(b.width+adj[0], b.height+adj[1]);
27001             }
27002             
27003             
27004             
27005             
27006             if(Ext.isIE){
27007                 setTimeout(function(){
27008                     if(el.dom.offsetWidth){
27009                         var b = el.getSize(true);
27010                         child.setSize(b.width+adj[0], b.height+adj[1]);
27011                     }
27012                 }, 10);
27013             }
27014         }
27015     },
27016
27017     
27018     snap : function(value, inc, min){
27019         if(!inc || !value){
27020             return value;
27021         }
27022         var newValue = value;
27023         var m = value % inc;
27024         if(m > 0){
27025             if(m > (inc/2)){
27026                 newValue = value + (inc-m);
27027             }else{
27028                 newValue = value - m;
27029             }
27030         }
27031         return Math.max(min, newValue);
27032     },
27033
27034     
27035     resizeElement : function(){
27036         var box = this.proxy.getBox();
27037         if(this.updateBox){
27038             this.el.setBox(box, false, this.animate, this.duration, null, this.easing);
27039         }else{
27040             this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);
27041         }
27042         this.updateChildSize();
27043         if(!this.dynamic){
27044             this.proxy.hide();
27045         }
27046         if(this.draggable && this.constrainTo){
27047             this.dd.resetConstraints();
27048             this.dd.constrainTo(this.constrainTo);
27049         }
27050         return box;
27051     },
27052
27053     
27054     constrain : function(v, diff, m, mx){
27055         if(v - diff < m){
27056             diff = v - m;
27057         }else if(v - diff > mx){
27058             diff = v - mx;
27059         }
27060         return diff;
27061     },
27062
27063     
27064     onMouseMove : function(e){
27065         if(this.enabled && this.activeHandle){
27066             try{
27067
27068             if(this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {
27069                 return;
27070             }
27071
27072             
27073             var curSize = this.curSize || this.startBox,
27074                 x = this.startBox.x, y = this.startBox.y,
27075                 ox = x,
27076                 oy = y,
27077                 w = curSize.width,
27078                 h = curSize.height,
27079                 ow = w,
27080                 oh = h,
27081                 mw = this.minWidth,
27082                 mh = this.minHeight,
27083                 mxw = this.maxWidth,
27084                 mxh = this.maxHeight,
27085                 wi = this.widthIncrement,
27086                 hi = this.heightIncrement,
27087                 eventXY = e.getXY(),
27088                 diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0])),
27089                 diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1])),
27090                 pos = this.activeHandle.position,
27091                 tw,
27092                 th;
27093
27094             switch(pos){
27095                 case 'east':
27096                     w += diffX;
27097                     w = Math.min(Math.max(mw, w), mxw);
27098                     break;
27099                 case 'south':
27100                     h += diffY;
27101                     h = Math.min(Math.max(mh, h), mxh);
27102                     break;
27103                 case 'southeast':
27104                     w += diffX;
27105                     h += diffY;
27106                     w = Math.min(Math.max(mw, w), mxw);
27107                     h = Math.min(Math.max(mh, h), mxh);
27108                     break;
27109                 case 'north':
27110                     diffY = this.constrain(h, diffY, mh, mxh);
27111                     y += diffY;
27112                     h -= diffY;
27113                     break;
27114                 case 'west':
27115                     diffX = this.constrain(w, diffX, mw, mxw);
27116                     x += diffX;
27117                     w -= diffX;
27118                     break;
27119                 case 'northeast':
27120                     w += diffX;
27121                     w = Math.min(Math.max(mw, w), mxw);
27122                     diffY = this.constrain(h, diffY, mh, mxh);
27123                     y += diffY;
27124                     h -= diffY;
27125                     break;
27126                 case 'northwest':
27127                     diffX = this.constrain(w, diffX, mw, mxw);
27128                     diffY = this.constrain(h, diffY, mh, mxh);
27129                     y += diffY;
27130                     h -= diffY;
27131                     x += diffX;
27132                     w -= diffX;
27133                     break;
27134                case 'southwest':
27135                     diffX = this.constrain(w, diffX, mw, mxw);
27136                     h += diffY;
27137                     h = Math.min(Math.max(mh, h), mxh);
27138                     x += diffX;
27139                     w -= diffX;
27140                     break;
27141             }
27142
27143             var sw = this.snap(w, wi, mw);
27144             var sh = this.snap(h, hi, mh);
27145             if(sw != w || sh != h){
27146                 switch(pos){
27147                     case 'northeast':
27148                         y -= sh - h;
27149                     break;
27150                     case 'north':
27151                         y -= sh - h;
27152                         break;
27153                     case 'southwest':
27154                         x -= sw - w;
27155                     break;
27156                     case 'west':
27157                         x -= sw - w;
27158                         break;
27159                     case 'northwest':
27160                         x -= sw - w;
27161                         y -= sh - h;
27162                     break;
27163                 }
27164                 w = sw;
27165                 h = sh;
27166             }
27167
27168             if(this.preserveRatio){
27169                 switch(pos){
27170                     case 'southeast':
27171                     case 'east':
27172                         h = oh * (w/ow);
27173                         h = Math.min(Math.max(mh, h), mxh);
27174                         w = ow * (h/oh);
27175                        break;
27176                     case 'south':
27177                         w = ow * (h/oh);
27178                         w = Math.min(Math.max(mw, w), mxw);
27179                         h = oh * (w/ow);
27180                         break;
27181                     case 'northeast':
27182                         w = ow * (h/oh);
27183                         w = Math.min(Math.max(mw, w), mxw);
27184                         h = oh * (w/ow);
27185                     break;
27186                     case 'north':
27187                         tw = w;
27188                         w = ow * (h/oh);
27189                         w = Math.min(Math.max(mw, w), mxw);
27190                         h = oh * (w/ow);
27191                         x += (tw - w) / 2;
27192                         break;
27193                     case 'southwest':
27194                         h = oh * (w/ow);
27195                         h = Math.min(Math.max(mh, h), mxh);
27196                         tw = w;
27197                         w = ow * (h/oh);
27198                         x += tw - w;
27199                         break;
27200                     case 'west':
27201                         th = h;
27202                         h = oh * (w/ow);
27203                         h = Math.min(Math.max(mh, h), mxh);
27204                         y += (th - h) / 2;
27205                         tw = w;
27206                         w = ow * (h/oh);
27207                         x += tw - w;
27208                        break;
27209                     case 'northwest':
27210                         tw = w;
27211                         th = h;
27212                         h = oh * (w/ow);
27213                         h = Math.min(Math.max(mh, h), mxh);
27214                         w = ow * (h/oh);
27215                         y += th - h;
27216                         x += tw - w;
27217                         break;
27218
27219                 }
27220             }
27221             this.proxy.setBounds(x, y, w, h);
27222             if(this.dynamic){
27223                 this.resizeElement();
27224             }
27225             }catch(ex){}
27226         }
27227     },
27228
27229     
27230     handleOver : function(){
27231         if(this.enabled){
27232             this.el.addClass('x-resizable-over');
27233         }
27234     },
27235
27236     
27237     handleOut : function(){
27238         if(!this.resizing){
27239             this.el.removeClass('x-resizable-over');
27240         }
27241     },
27242
27243     
27244     getEl : function(){
27245         return this.el;
27246     },
27247
27248     
27249     getResizeChild : function(){
27250         return this.resizeChild;
27251     },
27252
27253     
27254     destroy : function(removeEl){
27255         Ext.destroy(this.dd, this.overlay, this.proxy);
27256         this.overlay = null;
27257         this.proxy = null;
27258
27259         var ps = Ext.Resizable.positions;
27260         for(var k in ps){
27261             if(typeof ps[k] != 'function' && this[ps[k]]){
27262                 this[ps[k]].destroy();
27263             }
27264         }
27265         if(removeEl){
27266             this.el.update('');
27267             Ext.destroy(this.el);
27268             this.el = null;
27269         }
27270         this.purgeListeners();
27271     },
27272
27273     syncHandleHeight : function(){
27274         var h = this.el.getHeight(true);
27275         if(this.west){
27276             this.west.el.setHeight(h);
27277         }
27278         if(this.east){
27279             this.east.el.setHeight(h);
27280         }
27281     }
27282 });
27283
27284
27285
27286 Ext.Resizable.positions = {
27287     n: 'north', s: 'south', e: 'east', w: 'west', se: 'southeast', sw: 'southwest', nw: 'northwest', ne: 'northeast'
27288 };
27289
27290 Ext.Resizable.Handle = Ext.extend(Object, {
27291     constructor : function(rz, pos, disableTrackOver, transparent, cls){
27292        if(!this.tpl){
27293             
27294             var tpl = Ext.DomHelper.createTemplate(
27295                 {tag: 'div', cls: 'x-resizable-handle x-resizable-handle-{0}'}
27296             );
27297             tpl.compile();
27298             Ext.Resizable.Handle.prototype.tpl = tpl;
27299         }
27300         this.position = pos;
27301         this.rz = rz;
27302         this.el = this.tpl.append(rz.el.dom, [this.position], true);
27303         this.el.unselectable();
27304         if(transparent){
27305             this.el.setOpacity(0);
27306         }
27307         if(!Ext.isEmpty(cls)){
27308             this.el.addClass(cls);
27309         }
27310         this.el.on('mousedown', this.onMouseDown, this);
27311         if(!disableTrackOver){
27312             this.el.on({
27313                 scope: this,
27314                 mouseover: this.onMouseOver,
27315                 mouseout: this.onMouseOut
27316             });
27317         }
27318     },
27319
27320     
27321     afterResize : function(rz){
27322         
27323     },
27324     
27325     onMouseDown : function(e){
27326         this.rz.onMouseDown(this, e);
27327     },
27328     
27329     onMouseOver : function(e){
27330         this.rz.handleOver(this, e);
27331     },
27332     
27333     onMouseOut : function(e){
27334         this.rz.handleOut(this, e);
27335     },
27336     
27337     destroy : function(){
27338         Ext.destroy(this.el);
27339         this.el = null;
27340     }
27341 });
27342
27343 Ext.Window = Ext.extend(Ext.Panel, {
27344     
27345     
27346     
27347     
27348     
27349     
27350     
27351     
27352     
27353     
27354
27355     
27356     baseCls : 'x-window',
27357     
27358     resizable : true,
27359     
27360     draggable : true,
27361     
27362     closable : true,
27363     
27364     closeAction : 'close',
27365     
27366     constrain : false,
27367     
27368     constrainHeader : false,
27369     
27370     plain : false,
27371     
27372     minimizable : false,
27373     
27374     maximizable : false,
27375     
27376     minHeight : 100,
27377     
27378     minWidth : 200,
27379     
27380     expandOnShow : true,
27381     
27382     
27383     showAnimDuration: 0.25,
27384     
27385     
27386     hideAnimDuration: 0.25,
27387
27388     
27389     collapsible : false,
27390
27391     
27392     initHidden : undefined,
27393
27394     
27395     hidden : true,
27396
27397     
27398     
27399     
27400     
27401     
27402     elements : 'header,body',
27403     
27404     frame : true,
27405     
27406     floating : true,
27407
27408     
27409     initComponent : function(){
27410         this.initTools();
27411         Ext.Window.superclass.initComponent.call(this);
27412         this.addEvents(
27413             
27414             
27415             
27416             'resize',
27417             
27418             'maximize',
27419             
27420             'minimize',
27421             
27422             'restore'
27423         );
27424         
27425         if(Ext.isDefined(this.initHidden)){
27426             this.hidden = this.initHidden;
27427         }
27428         if(this.hidden === false){
27429             this.hidden = true;
27430             this.show();
27431         }
27432     },
27433
27434     
27435     getState : function(){
27436         return Ext.apply(Ext.Window.superclass.getState.call(this) || {}, this.getBox(true));
27437     },
27438
27439     
27440     onRender : function(ct, position){
27441         Ext.Window.superclass.onRender.call(this, ct, position);
27442
27443         if(this.plain){
27444             this.el.addClass('x-window-plain');
27445         }
27446
27447         
27448         this.focusEl = this.el.createChild({
27449                     tag: 'a', href:'#', cls:'x-dlg-focus',
27450                     tabIndex:'-1', html: '&#160;'});
27451         this.focusEl.swallowEvent('click', true);
27452
27453         this.proxy = this.el.createProxy('x-window-proxy');
27454         this.proxy.enableDisplayMode('block');
27455
27456         if(this.modal){
27457             this.mask = this.container.createChild({cls:'ext-el-mask'}, this.el.dom);
27458             this.mask.enableDisplayMode('block');
27459             this.mask.hide();
27460             this.mon(this.mask, 'click', this.focus, this);
27461         }
27462         if(this.maximizable){
27463             this.mon(this.header, 'dblclick', this.toggleMaximize, this);
27464         }
27465     },
27466
27467     
27468     initEvents : function(){
27469         Ext.Window.superclass.initEvents.call(this);
27470         if(this.animateTarget){
27471             this.setAnimateTarget(this.animateTarget);
27472         }
27473
27474         if(this.resizable){
27475             this.resizer = new Ext.Resizable(this.el, {
27476                 minWidth: this.minWidth,
27477                 minHeight:this.minHeight,
27478                 handles: this.resizeHandles || 'all',
27479                 pinned: true,
27480                 resizeElement : this.resizerAction,
27481                 handleCls: 'x-window-handle'
27482             });
27483             this.resizer.window = this;
27484             this.mon(this.resizer, 'beforeresize', this.beforeResize, this);
27485         }
27486
27487         if(this.draggable){
27488             this.header.addClass('x-window-draggable');
27489         }
27490         this.mon(this.el, 'mousedown', this.toFront, this);
27491         this.manager = this.manager || Ext.WindowMgr;
27492         this.manager.register(this);
27493         if(this.maximized){
27494             this.maximized = false;
27495             this.maximize();
27496         }
27497         if(this.closable){
27498             var km = this.getKeyMap();
27499             km.on(27, this.onEsc, this);
27500             km.disable();
27501         }
27502     },
27503
27504     initDraggable : function(){
27505         
27506         this.dd = new Ext.Window.DD(this);
27507     },
27508
27509    
27510     onEsc : function(k, e){
27511         e.stopEvent();
27512         this[this.closeAction]();
27513     },
27514
27515     
27516     beforeDestroy : function(){
27517         if(this.rendered){
27518             this.hide();
27519             this.clearAnchor();
27520             Ext.destroy(
27521                 this.focusEl,
27522                 this.resizer,
27523                 this.dd,
27524                 this.proxy,
27525                 this.mask
27526             );
27527         }
27528         Ext.Window.superclass.beforeDestroy.call(this);
27529     },
27530
27531     
27532     onDestroy : function(){
27533         if(this.manager){
27534             this.manager.unregister(this);
27535         }
27536         Ext.Window.superclass.onDestroy.call(this);
27537     },
27538
27539     
27540     initTools : function(){
27541         if(this.minimizable){
27542             this.addTool({
27543                 id: 'minimize',
27544                 handler: this.minimize.createDelegate(this, [])
27545             });
27546         }
27547         if(this.maximizable){
27548             this.addTool({
27549                 id: 'maximize',
27550                 handler: this.maximize.createDelegate(this, [])
27551             });
27552             this.addTool({
27553                 id: 'restore',
27554                 handler: this.restore.createDelegate(this, []),
27555                 hidden:true
27556             });
27557         }
27558         if(this.closable){
27559             this.addTool({
27560                 id: 'close',
27561                 handler: this[this.closeAction].createDelegate(this, [])
27562             });
27563         }
27564     },
27565
27566     
27567     resizerAction : function(){
27568         var box = this.proxy.getBox();
27569         this.proxy.hide();
27570         this.window.handleResize(box);
27571         return box;
27572     },
27573
27574     
27575     beforeResize : function(){
27576         this.resizer.minHeight = Math.max(this.minHeight, this.getFrameHeight() + 40); 
27577         this.resizer.minWidth = Math.max(this.minWidth, this.getFrameWidth() + 40);
27578         this.resizeBox = this.el.getBox();
27579     },
27580
27581     
27582     updateHandles : function(){
27583         if(Ext.isIE && this.resizer){
27584             this.resizer.syncHandleHeight();
27585             this.el.repaint();
27586         }
27587     },
27588
27589     
27590     handleResize : function(box){
27591         var rz = this.resizeBox;
27592         if(rz.x != box.x || rz.y != box.y){
27593             this.updateBox(box);
27594         }else{
27595             this.setSize(box);
27596             if (Ext.isIE6 && Ext.isStrict) {
27597                 this.doLayout();
27598             }
27599         }
27600         this.focus();
27601         this.updateHandles();
27602         this.saveState();
27603     },
27604
27605     
27606     focus : function(){
27607         var f = this.focusEl,
27608             db = this.defaultButton,
27609             t = typeof db,
27610             el,
27611             ct;
27612         if(Ext.isDefined(db)){
27613             if(Ext.isNumber(db) && this.fbar){
27614                 f = this.fbar.items.get(db);
27615             }else if(Ext.isString(db)){
27616                 f = Ext.getCmp(db);
27617             }else{
27618                 f = db;
27619             }
27620             el = f.getEl();
27621             ct = Ext.getDom(this.container);
27622             if (el && ct) {
27623                 if (ct != document.body && !Ext.lib.Region.getRegion(ct).contains(Ext.lib.Region.getRegion(el.dom))){
27624                     return;
27625                 }
27626             }
27627         }
27628         f = f || this.focusEl;
27629         f.focus.defer(10, f);
27630     },
27631
27632     
27633     setAnimateTarget : function(el){
27634         el = Ext.get(el);
27635         this.animateTarget = el;
27636     },
27637
27638     
27639     beforeShow : function(){
27640         delete this.el.lastXY;
27641         delete this.el.lastLT;
27642         if(this.x === undefined || this.y === undefined){
27643             var xy = this.el.getAlignToXY(this.container, 'c-c');
27644             var pos = this.el.translatePoints(xy[0], xy[1]);
27645             this.x = this.x === undefined? pos.left : this.x;
27646             this.y = this.y === undefined? pos.top : this.y;
27647         }
27648         this.el.setLeftTop(this.x, this.y);
27649
27650         if(this.expandOnShow){
27651             this.expand(false);
27652         }
27653
27654         if(this.modal){
27655             Ext.getBody().addClass('x-body-masked');
27656             this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
27657             this.mask.show();
27658         }
27659     },
27660
27661     
27662     show : function(animateTarget, cb, scope){
27663         if(!this.rendered){
27664             this.render(Ext.getBody());
27665         }
27666         if(this.hidden === false){
27667             this.toFront();
27668             return this;
27669         }
27670         if(this.fireEvent('beforeshow', this) === false){
27671             return this;
27672         }
27673         if(cb){
27674             this.on('show', cb, scope, {single:true});
27675         }
27676         this.hidden = false;
27677         if(Ext.isDefined(animateTarget)){
27678             this.setAnimateTarget(animateTarget);
27679         }
27680         this.beforeShow();
27681         if(this.animateTarget){
27682             this.animShow();
27683         }else{
27684             this.afterShow();
27685         }
27686         return this;
27687     },
27688
27689     
27690     afterShow : function(isAnim){
27691         if (this.isDestroyed){
27692             return false;
27693         }
27694         this.proxy.hide();
27695         this.el.setStyle('display', 'block');
27696         this.el.show();
27697         if(this.maximized){
27698             this.fitContainer();
27699         }
27700         if(Ext.isMac && Ext.isGecko2){ 
27701             this.cascade(this.setAutoScroll);
27702         }
27703
27704         if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
27705             Ext.EventManager.onWindowResize(this.onWindowResize, this);
27706         }
27707         this.doConstrain();
27708         this.doLayout();
27709         if(this.keyMap){
27710             this.keyMap.enable();
27711         }
27712         this.toFront();
27713         this.updateHandles();
27714         if(isAnim && (Ext.isIE || Ext.isWebKit)){
27715             var sz = this.getSize();
27716             this.onResize(sz.width, sz.height);
27717         }
27718         this.onShow();
27719         this.fireEvent('show', this);
27720     },
27721
27722     
27723     animShow : function(){
27724         this.proxy.show();
27725         this.proxy.setBox(this.animateTarget.getBox());
27726         this.proxy.setOpacity(0);
27727         var b = this.getBox();
27728         this.el.setStyle('display', 'none');
27729         this.proxy.shift(Ext.apply(b, {
27730             callback: this.afterShow.createDelegate(this, [true], false),
27731             scope: this,
27732             easing: 'easeNone',
27733             duration: this.showAnimDuration,
27734             opacity: 0.5
27735         }));
27736     },
27737
27738     
27739     hide : function(animateTarget, cb, scope){
27740         if(this.hidden || this.fireEvent('beforehide', this) === false){
27741             return this;
27742         }
27743         if(cb){
27744             this.on('hide', cb, scope, {single:true});
27745         }
27746         this.hidden = true;
27747         if(animateTarget !== undefined){
27748             this.setAnimateTarget(animateTarget);
27749         }
27750         if(this.modal){
27751             this.mask.hide();
27752             Ext.getBody().removeClass('x-body-masked');
27753         }
27754         if(this.animateTarget){
27755             this.animHide();
27756         }else{
27757             this.el.hide();
27758             this.afterHide();
27759         }
27760         return this;
27761     },
27762
27763     
27764     afterHide : function(){
27765         this.proxy.hide();
27766         if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
27767             Ext.EventManager.removeResizeListener(this.onWindowResize, this);
27768         }
27769         if(this.keyMap){
27770             this.keyMap.disable();
27771         }
27772         this.onHide();
27773         this.fireEvent('hide', this);
27774     },
27775
27776     
27777     animHide : function(){
27778         this.proxy.setOpacity(0.5);
27779         this.proxy.show();
27780         var tb = this.getBox(false);
27781         this.proxy.setBox(tb);
27782         this.el.hide();
27783         this.proxy.shift(Ext.apply(this.animateTarget.getBox(), {
27784             callback: this.afterHide,
27785             scope: this,
27786             duration: this.hideAnimDuration,
27787             easing: 'easeNone',
27788             opacity: 0
27789         }));
27790     },
27791
27792     
27793     onShow : Ext.emptyFn,
27794
27795     
27796     onHide : Ext.emptyFn,
27797
27798     
27799     onWindowResize : function(){
27800         if(this.maximized){
27801             this.fitContainer();
27802         }
27803         if(this.modal){
27804             this.mask.setSize('100%', '100%');
27805             var force = this.mask.dom.offsetHeight;
27806             this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
27807         }
27808         this.doConstrain();
27809     },
27810
27811     
27812     doConstrain : function(){
27813         if(this.constrain || this.constrainHeader){
27814             var offsets;
27815             if(this.constrain){
27816                 offsets = {
27817                     right:this.el.shadowOffset,
27818                     left:this.el.shadowOffset,
27819                     bottom:this.el.shadowOffset
27820                 };
27821             }else {
27822                 var s = this.getSize();
27823                 offsets = {
27824                     right:-(s.width - 100),
27825                     bottom:-(s.height - 25)
27826                 };
27827             }
27828
27829             var xy = this.el.getConstrainToXY(this.container, true, offsets);
27830             if(xy){
27831                 this.setPosition(xy[0], xy[1]);
27832             }
27833         }
27834     },
27835
27836     
27837     ghost : function(cls){
27838         var ghost = this.createGhost(cls);
27839         var box = this.getBox(true);
27840         ghost.setLeftTop(box.x, box.y);
27841         ghost.setWidth(box.width);
27842         this.el.hide();
27843         this.activeGhost = ghost;
27844         return ghost;
27845     },
27846
27847     
27848     unghost : function(show, matchPosition){
27849         if(!this.activeGhost) {
27850             return;
27851         }
27852         if(show !== false){
27853             this.el.show();
27854             this.focus.defer(10, this);
27855             if(Ext.isMac && Ext.isGecko2){ 
27856                 this.cascade(this.setAutoScroll);
27857             }
27858         }
27859         if(matchPosition !== false){
27860             this.setPosition(this.activeGhost.getLeft(true), this.activeGhost.getTop(true));
27861         }
27862         this.activeGhost.hide();
27863         this.activeGhost.remove();
27864         delete this.activeGhost;
27865     },
27866
27867     
27868     minimize : function(){
27869         this.fireEvent('minimize', this);
27870         return this;
27871     },
27872
27873     
27874     close : function(){
27875         if(this.fireEvent('beforeclose', this) !== false){
27876             if(this.hidden){
27877                 this.doClose();
27878             }else{
27879                 this.hide(null, this.doClose, this);
27880             }
27881         }
27882     },
27883
27884     
27885     doClose : function(){
27886         this.fireEvent('close', this);
27887         this.destroy();
27888     },
27889
27890     
27891     maximize : function(){
27892         if(!this.maximized){
27893             this.expand(false);
27894             this.restoreSize = this.getSize();
27895             this.restorePos = this.getPosition(true);
27896             if (this.maximizable){
27897                 this.tools.maximize.hide();
27898                 this.tools.restore.show();
27899             }
27900             this.maximized = true;
27901             this.el.disableShadow();
27902
27903             if(this.dd){
27904                 this.dd.lock();
27905             }
27906             if(this.collapsible){
27907                 this.tools.toggle.hide();
27908             }
27909             this.el.addClass('x-window-maximized');
27910             this.container.addClass('x-window-maximized-ct');
27911
27912             this.setPosition(0, 0);
27913             this.fitContainer();
27914             this.fireEvent('maximize', this);
27915         }
27916         return this;
27917     },
27918
27919     
27920     restore : function(){
27921         if(this.maximized){
27922             var t = this.tools;
27923             this.el.removeClass('x-window-maximized');
27924             if(t.restore){
27925                 t.restore.hide();
27926             }
27927             if(t.maximize){
27928                 t.maximize.show();
27929             }
27930             this.setPosition(this.restorePos[0], this.restorePos[1]);
27931             this.setSize(this.restoreSize.width, this.restoreSize.height);
27932             delete this.restorePos;
27933             delete this.restoreSize;
27934             this.maximized = false;
27935             this.el.enableShadow(true);
27936
27937             if(this.dd){
27938                 this.dd.unlock();
27939             }
27940             if(this.collapsible && t.toggle){
27941                 t.toggle.show();
27942             }
27943             this.container.removeClass('x-window-maximized-ct');
27944
27945             this.doConstrain();
27946             this.fireEvent('restore', this);
27947         }
27948         return this;
27949     },
27950
27951     
27952     toggleMaximize : function(){
27953         return this[this.maximized ? 'restore' : 'maximize']();
27954     },
27955
27956     
27957     fitContainer : function(){
27958         var vs = this.container.getViewSize(false);
27959         this.setSize(vs.width, vs.height);
27960     },
27961
27962     
27963     
27964     setZIndex : function(index){
27965         if(this.modal){
27966             this.mask.setStyle('z-index', index);
27967         }
27968         this.el.setZIndex(++index);
27969         index += 5;
27970
27971         if(this.resizer){
27972             this.resizer.proxy.setStyle('z-index', ++index);
27973         }
27974
27975         this.lastZIndex = index;
27976     },
27977
27978     
27979     alignTo : function(element, position, offsets){
27980         var xy = this.el.getAlignToXY(element, position, offsets);
27981         this.setPagePosition(xy[0], xy[1]);
27982         return this;
27983     },
27984
27985     
27986     anchorTo : function(el, alignment, offsets, monitorScroll){
27987         this.clearAnchor();
27988         this.anchorTarget = {
27989             el: el,
27990             alignment: alignment,
27991             offsets: offsets
27992         };
27993
27994         Ext.EventManager.onWindowResize(this.doAnchor, this);
27995         var tm = typeof monitorScroll;
27996         if(tm != 'undefined'){
27997             Ext.EventManager.on(window, 'scroll', this.doAnchor, this,
27998                 {buffer: tm == 'number' ? monitorScroll : 50});
27999         }
28000         return this.doAnchor();
28001     },
28002
28003     
28004     doAnchor : function(){
28005         var o = this.anchorTarget;
28006         this.alignTo(o.el, o.alignment, o.offsets);
28007         return this;
28008     },
28009
28010     
28011     clearAnchor : function(){
28012         if(this.anchorTarget){
28013             Ext.EventManager.removeResizeListener(this.doAnchor, this);
28014             Ext.EventManager.un(window, 'scroll', this.doAnchor, this);
28015             delete this.anchorTarget;
28016         }
28017         return this;
28018     },
28019
28020     
28021     toFront : function(e){
28022         if(this.manager.bringToFront(this)){
28023             if(!e || !e.getTarget().focus){
28024                 this.focus();
28025             }
28026         }
28027         return this;
28028     },
28029
28030     
28031     setActive : function(active){
28032         if(active){
28033             if(!this.maximized){
28034                 this.el.enableShadow(true);
28035             }
28036             this.fireEvent('activate', this);
28037         }else{
28038             this.el.disableShadow();
28039             this.fireEvent('deactivate', this);
28040         }
28041     },
28042
28043     
28044     toBack : function(){
28045         this.manager.sendToBack(this);
28046         return this;
28047     },
28048
28049     
28050     center : function(){
28051         var xy = this.el.getAlignToXY(this.container, 'c-c');
28052         this.setPagePosition(xy[0], xy[1]);
28053         return this;
28054     }
28055
28056     
28057 });
28058 Ext.reg('window', Ext.Window);
28059
28060
28061 Ext.Window.DD = Ext.extend(Ext.dd.DD, {
28062     
28063     constructor : function(win){
28064         this.win = win;
28065         Ext.Window.DD.superclass.constructor.call(this, win.el.id, 'WindowDD-'+win.id);
28066         this.setHandleElId(win.header.id);
28067         this.scroll = false;        
28068     },
28069     
28070     moveOnly:true,
28071     headerOffsets:[100, 25],
28072     startDrag : function(){
28073         var w = this.win;
28074         this.proxy = w.ghost(w.initialConfig.cls);
28075         if(w.constrain !== false){
28076             var so = w.el.shadowOffset;
28077             this.constrainTo(w.container, {right: so, left: so, bottom: so});
28078         }else if(w.constrainHeader !== false){
28079             var s = this.proxy.getSize();
28080             this.constrainTo(w.container, {right: -(s.width-this.headerOffsets[0]), bottom: -(s.height-this.headerOffsets[1])});
28081         }
28082     },
28083     b4Drag : Ext.emptyFn,
28084
28085     onDrag : function(e){
28086         this.alignElWithMouse(this.proxy, e.getPageX(), e.getPageY());
28087     },
28088
28089     endDrag : function(e){
28090         this.win.unghost();
28091         this.win.saveState();
28092     }
28093 });
28094
28095 Ext.WindowGroup = function(){
28096     var list = {};
28097     var accessList = [];
28098     var front = null;
28099
28100     
28101     var sortWindows = function(d1, d2){
28102         return (!d1._lastAccess || d1._lastAccess < d2._lastAccess) ? -1 : 1;
28103     };
28104
28105     
28106     var orderWindows = function(){
28107         var a = accessList, len = a.length;
28108         if(len > 0){
28109             a.sort(sortWindows);
28110             var seed = a[0].manager.zseed;
28111             for(var i = 0; i < len; i++){
28112                 var win = a[i];
28113                 if(win && !win.hidden){
28114                     win.setZIndex(seed + (i*10));
28115                 }
28116             }
28117         }
28118         activateLast();
28119     };
28120
28121     
28122     var setActiveWin = function(win){
28123         if(win != front){
28124             if(front){
28125                 front.setActive(false);
28126             }
28127             front = win;
28128             if(win){
28129                 win.setActive(true);
28130             }
28131         }
28132     };
28133
28134     
28135     var activateLast = function(){
28136         for(var i = accessList.length-1; i >=0; --i) {
28137             if(!accessList[i].hidden){
28138                 setActiveWin(accessList[i]);
28139                 return;
28140             }
28141         }
28142         
28143         setActiveWin(null);
28144     };
28145
28146     return {
28147         
28148         zseed : 9000,
28149
28150         
28151         register : function(win){
28152             if(win.manager){
28153                 win.manager.unregister(win);
28154             }
28155             win.manager = this;
28156
28157             list[win.id] = win;
28158             accessList.push(win);
28159             win.on('hide', activateLast);
28160         },
28161
28162         
28163         unregister : function(win){
28164             delete win.manager;
28165             delete list[win.id];
28166             win.un('hide', activateLast);
28167             accessList.remove(win);
28168         },
28169
28170         
28171         get : function(id){
28172             return typeof id == "object" ? id : list[id];
28173         },
28174
28175         
28176         bringToFront : function(win){
28177             win = this.get(win);
28178             if(win != front){
28179                 win._lastAccess = new Date().getTime();
28180                 orderWindows();
28181                 return true;
28182             }
28183             return false;
28184         },
28185
28186         
28187         sendToBack : function(win){
28188             win = this.get(win);
28189             win._lastAccess = -(new Date().getTime());
28190             orderWindows();
28191             return win;
28192         },
28193
28194         
28195         hideAll : function(){
28196             for(var id in list){
28197                 if(list[id] && typeof list[id] != "function" && list[id].isVisible()){
28198                     list[id].hide();
28199                 }
28200             }
28201         },
28202
28203         
28204         getActive : function(){
28205             return front;
28206         },
28207
28208         
28209         getBy : function(fn, scope){
28210             var r = [];
28211             for(var i = accessList.length-1; i >=0; --i) {
28212                 var win = accessList[i];
28213                 if(fn.call(scope||win, win) !== false){
28214                     r.push(win);
28215                 }
28216             }
28217             return r;
28218         },
28219
28220         
28221         each : function(fn, scope){
28222             for(var id in list){
28223                 if(list[id] && typeof list[id] != "function"){
28224                     if(fn.call(scope || list[id], list[id]) === false){
28225                         return;
28226                     }
28227                 }
28228             }
28229         }
28230     };
28231 };
28232
28233
28234
28235 Ext.WindowMgr = new Ext.WindowGroup();
28236 Ext.MessageBox = function(){
28237     var dlg, opt, mask, waitTimer,
28238         bodyEl, msgEl, textboxEl, textareaEl, progressBar, pp, iconEl, spacerEl,
28239         buttons, activeTextEl, bwidth, bufferIcon = '', iconCls = '',
28240         buttonNames = ['ok', 'yes', 'no', 'cancel'];
28241
28242     
28243     var handleButton = function(button){
28244         buttons[button].blur();
28245         if(dlg.isVisible()){
28246             dlg.hide();
28247             handleHide();
28248             Ext.callback(opt.fn, opt.scope||window, [button, activeTextEl.dom.value, opt], 1);
28249         }
28250     };
28251
28252     
28253     var handleHide = function(){
28254         if(opt && opt.cls){
28255             dlg.el.removeClass(opt.cls);
28256         }
28257         progressBar.reset();        
28258     };
28259
28260     
28261     var handleEsc = function(d, k, e){
28262         if(opt && opt.closable !== false){
28263             dlg.hide();
28264             handleHide();
28265         }
28266         if(e){
28267             e.stopEvent();
28268         }
28269     };
28270
28271     
28272     var updateButtons = function(b){
28273         var width = 0,
28274             cfg;
28275         if(!b){
28276             Ext.each(buttonNames, function(name){
28277                 buttons[name].hide();
28278             });
28279             return width;
28280         }
28281         dlg.footer.dom.style.display = '';
28282         Ext.iterate(buttons, function(name, btn){
28283             cfg = b[name];
28284             if(cfg){
28285                 btn.show();
28286                 btn.setText(Ext.isString(cfg) ? cfg : Ext.MessageBox.buttonText[name]);
28287                 width += btn.getEl().getWidth() + 15;
28288             }else{
28289                 btn.hide();
28290             }
28291         });
28292         return width;
28293     };
28294
28295     return {
28296         
28297         getDialog : function(titleText){
28298            if(!dlg){
28299                 var btns = [];
28300                 
28301                 buttons = {};
28302                 Ext.each(buttonNames, function(name){
28303                     btns.push(buttons[name] = new Ext.Button({
28304                         text: this.buttonText[name],
28305                         handler: handleButton.createCallback(name),
28306                         hideMode: 'offsets'
28307                     }));
28308                 }, this);
28309                 dlg = new Ext.Window({
28310                     autoCreate : true,
28311                     title:titleText,
28312                     resizable:false,
28313                     constrain:true,
28314                     constrainHeader:true,
28315                     minimizable : false,
28316                     maximizable : false,
28317                     stateful: false,
28318                     modal: true,
28319                     shim:true,
28320                     buttonAlign:"center",
28321                     width:400,
28322                     height:100,
28323                     minHeight: 80,
28324                     plain:true,
28325                     footer:true,
28326                     closable:true,
28327                     close : function(){
28328                         if(opt && opt.buttons && opt.buttons.no && !opt.buttons.cancel){
28329                             handleButton("no");
28330                         }else{
28331                             handleButton("cancel");
28332                         }
28333                     },
28334                     fbar: new Ext.Toolbar({
28335                         items: btns,
28336                         enableOverflow: false
28337                     })
28338                 });
28339                 dlg.render(document.body);
28340                 dlg.getEl().addClass('x-window-dlg');
28341                 mask = dlg.mask;
28342                 bodyEl = dlg.body.createChild({
28343                     html:'<div class="ext-mb-icon"></div><div class="ext-mb-content"><span class="ext-mb-text"></span><br /><div class="ext-mb-fix-cursor"><input type="text" class="ext-mb-input" /><textarea class="ext-mb-textarea"></textarea></div></div>'
28344                 });
28345                 iconEl = Ext.get(bodyEl.dom.firstChild);
28346                 var contentEl = bodyEl.dom.childNodes[1];
28347                 msgEl = Ext.get(contentEl.firstChild);
28348                 textboxEl = Ext.get(contentEl.childNodes[2].firstChild);
28349                 textboxEl.enableDisplayMode();
28350                 textboxEl.addKeyListener([10,13], function(){
28351                     if(dlg.isVisible() && opt && opt.buttons){
28352                         if(opt.buttons.ok){
28353                             handleButton("ok");
28354                         }else if(opt.buttons.yes){
28355                             handleButton("yes");
28356                         }
28357                     }
28358                 });
28359                 textareaEl = Ext.get(contentEl.childNodes[2].childNodes[1]);
28360                 textareaEl.enableDisplayMode();
28361                 progressBar = new Ext.ProgressBar({
28362                     renderTo:bodyEl
28363                 });
28364                bodyEl.createChild({cls:'x-clear'});
28365             }
28366             return dlg;
28367         },
28368
28369         
28370         updateText : function(text){
28371             if(!dlg.isVisible() && !opt.width){
28372                 dlg.setSize(this.maxWidth, 100); 
28373             }
28374             
28375             msgEl.update(text ? text + ' ' : '&#160;');
28376
28377             var iw = iconCls != '' ? (iconEl.getWidth() + iconEl.getMargins('lr')) : 0,
28378                 mw = msgEl.getWidth() + msgEl.getMargins('lr'),
28379                 fw = dlg.getFrameWidth('lr'),
28380                 bw = dlg.body.getFrameWidth('lr'),
28381                 w;
28382                 
28383             w = Math.max(Math.min(opt.width || iw+mw+fw+bw, opt.maxWidth || this.maxWidth),
28384                     Math.max(opt.minWidth || this.minWidth, bwidth || 0));
28385
28386             if(opt.prompt === true){
28387                 activeTextEl.setWidth(w-iw-fw-bw);
28388             }
28389             if(opt.progress === true || opt.wait === true){
28390                 progressBar.setSize(w-iw-fw-bw);
28391             }
28392             if(Ext.isIE && w == bwidth){
28393                 w += 4; 
28394             }
28395             msgEl.update(text || '&#160;');
28396             dlg.setSize(w, 'auto').center();
28397             return this;
28398         },
28399
28400         
28401         updateProgress : function(value, progressText, msg){
28402             progressBar.updateProgress(value, progressText);
28403             if(msg){
28404                 this.updateText(msg);
28405             }
28406             return this;
28407         },
28408
28409         
28410         isVisible : function(){
28411             return dlg && dlg.isVisible();
28412         },
28413
28414         
28415         hide : function(){
28416             var proxy = dlg ? dlg.activeGhost : null;
28417             if(this.isVisible() || proxy){
28418                 dlg.hide();
28419                 handleHide();
28420                 if (proxy){
28421                     
28422                     
28423                     dlg.unghost(false, false);
28424                 } 
28425             }
28426             return this;
28427         },
28428
28429         
28430         show : function(options){
28431             if(this.isVisible()){
28432                 this.hide();
28433             }
28434             opt = options;
28435             var d = this.getDialog(opt.title || "&#160;");
28436
28437             d.setTitle(opt.title || "&#160;");
28438             var allowClose = (opt.closable !== false && opt.progress !== true && opt.wait !== true);
28439             d.tools.close.setDisplayed(allowClose);
28440             activeTextEl = textboxEl;
28441             opt.prompt = opt.prompt || (opt.multiline ? true : false);
28442             if(opt.prompt){
28443                 if(opt.multiline){
28444                     textboxEl.hide();
28445                     textareaEl.show();
28446                     textareaEl.setHeight(Ext.isNumber(opt.multiline) ? opt.multiline : this.defaultTextHeight);
28447                     activeTextEl = textareaEl;
28448                 }else{
28449                     textboxEl.show();
28450                     textareaEl.hide();
28451                 }
28452             }else{
28453                 textboxEl.hide();
28454                 textareaEl.hide();
28455             }
28456             activeTextEl.dom.value = opt.value || "";
28457             if(opt.prompt){
28458                 d.focusEl = activeTextEl;
28459             }else{
28460                 var bs = opt.buttons;
28461                 var db = null;
28462                 if(bs && bs.ok){
28463                     db = buttons["ok"];
28464                 }else if(bs && bs.yes){
28465                     db = buttons["yes"];
28466                 }
28467                 if (db){
28468                     d.focusEl = db;
28469                 }
28470             }
28471             if(Ext.isDefined(opt.iconCls)){
28472               d.setIconClass(opt.iconCls);
28473             }
28474             this.setIcon(Ext.isDefined(opt.icon) ? opt.icon : bufferIcon);
28475             bwidth = updateButtons(opt.buttons);
28476             progressBar.setVisible(opt.progress === true || opt.wait === true);
28477             this.updateProgress(0, opt.progressText);
28478             this.updateText(opt.msg);
28479             if(opt.cls){
28480                 d.el.addClass(opt.cls);
28481             }
28482             d.proxyDrag = opt.proxyDrag === true;
28483             d.modal = opt.modal !== false;
28484             d.mask = opt.modal !== false ? mask : false;
28485             if(!d.isVisible()){
28486                 
28487                 document.body.appendChild(dlg.el.dom);
28488                 d.setAnimateTarget(opt.animEl);
28489                 
28490                 d.on('show', function(){
28491                     if(allowClose === true){
28492                         d.keyMap.enable();
28493                     }else{
28494                         d.keyMap.disable();
28495                     }
28496                 }, this, {single:true});
28497                 d.show(opt.animEl);
28498             }
28499             if(opt.wait === true){
28500                 progressBar.wait(opt.waitConfig);
28501             }
28502             return this;
28503         },
28504
28505         
28506         setIcon : function(icon){
28507             if(!dlg){
28508                 bufferIcon = icon;
28509                 return;
28510             }
28511             bufferIcon = undefined;
28512             if(icon && icon != ''){
28513                 iconEl.removeClass('x-hidden');
28514                 iconEl.replaceClass(iconCls, icon);
28515                 bodyEl.addClass('x-dlg-icon');
28516                 iconCls = icon;
28517             }else{
28518                 iconEl.replaceClass(iconCls, 'x-hidden');
28519                 bodyEl.removeClass('x-dlg-icon');
28520                 iconCls = '';
28521             }
28522             return this;
28523         },
28524
28525         
28526         progress : function(title, msg, progressText){
28527             this.show({
28528                 title : title,
28529                 msg : msg,
28530                 buttons: false,
28531                 progress:true,
28532                 closable:false,
28533                 minWidth: this.minProgressWidth,
28534                 progressText: progressText
28535             });
28536             return this;
28537         },
28538
28539         
28540         wait : function(msg, title, config){
28541             this.show({
28542                 title : title,
28543                 msg : msg,
28544                 buttons: false,
28545                 closable:false,
28546                 wait:true,
28547                 modal:true,
28548                 minWidth: this.minProgressWidth,
28549                 waitConfig: config
28550             });
28551             return this;
28552         },
28553
28554         
28555         alert : function(title, msg, fn, scope){
28556             this.show({
28557                 title : title,
28558                 msg : msg,
28559                 buttons: this.OK,
28560                 fn: fn,
28561                 scope : scope,
28562                 minWidth: this.minWidth
28563             });
28564             return this;
28565         },
28566
28567         
28568         confirm : function(title, msg, fn, scope){
28569             this.show({
28570                 title : title,
28571                 msg : msg,
28572                 buttons: this.YESNO,
28573                 fn: fn,
28574                 scope : scope,
28575                 icon: this.QUESTION,
28576                 minWidth: this.minWidth
28577             });
28578             return this;
28579         },
28580
28581         
28582         prompt : function(title, msg, fn, scope, multiline, value){
28583             this.show({
28584                 title : title,
28585                 msg : msg,
28586                 buttons: this.OKCANCEL,
28587                 fn: fn,
28588                 minWidth: this.minPromptWidth,
28589                 scope : scope,
28590                 prompt:true,
28591                 multiline: multiline,
28592                 value: value
28593             });
28594             return this;
28595         },
28596
28597         
28598         OK : {ok:true},
28599         
28600         CANCEL : {cancel:true},
28601         
28602         OKCANCEL : {ok:true, cancel:true},
28603         
28604         YESNO : {yes:true, no:true},
28605         
28606         YESNOCANCEL : {yes:true, no:true, cancel:true},
28607         
28608         INFO : 'ext-mb-info',
28609         
28610         WARNING : 'ext-mb-warning',
28611         
28612         QUESTION : 'ext-mb-question',
28613         
28614         ERROR : 'ext-mb-error',
28615
28616         
28617         defaultTextHeight : 75,
28618         
28619         maxWidth : 600,
28620         
28621         minWidth : 100,
28622         
28623         minProgressWidth : 250,
28624         
28625         minPromptWidth: 250,
28626         
28627         buttonText : {
28628             ok : "OK",
28629             cancel : "Cancel",
28630             yes : "Yes",
28631             no : "No"
28632         }
28633     };
28634 }();
28635
28636
28637 Ext.Msg = Ext.MessageBox;
28638 Ext.dd.PanelProxy  = Ext.extend(Object, {
28639     
28640     constructor : function(panel, config){
28641         this.panel = panel;
28642         this.id = this.panel.id +'-ddproxy';
28643         Ext.apply(this, config);        
28644     },
28645     
28646     
28647     insertProxy : true,
28648
28649     
28650     setStatus : Ext.emptyFn,
28651     reset : Ext.emptyFn,
28652     update : Ext.emptyFn,
28653     stop : Ext.emptyFn,
28654     sync: Ext.emptyFn,
28655
28656     
28657     getEl : function(){
28658         return this.ghost;
28659     },
28660
28661     
28662     getGhost : function(){
28663         return this.ghost;
28664     },
28665
28666     
28667     getProxy : function(){
28668         return this.proxy;
28669     },
28670
28671     
28672     hide : function(){
28673         if(this.ghost){
28674             if(this.proxy){
28675                 this.proxy.remove();
28676                 delete this.proxy;
28677             }
28678             this.panel.el.dom.style.display = '';
28679             this.ghost.remove();
28680             delete this.ghost;
28681         }
28682     },
28683
28684     
28685     show : function(){
28686         if(!this.ghost){
28687             this.ghost = this.panel.createGhost(this.panel.initialConfig.cls, undefined, Ext.getBody());
28688             this.ghost.setXY(this.panel.el.getXY());
28689             if(this.insertProxy){
28690                 this.proxy = this.panel.el.insertSibling({cls:'x-panel-dd-spacer'});
28691                 this.proxy.setSize(this.panel.getSize());
28692             }
28693             this.panel.el.dom.style.display = 'none';
28694         }
28695     },
28696
28697     
28698     repair : function(xy, callback, scope){
28699         this.hide();
28700         if(typeof callback == "function"){
28701             callback.call(scope || this);
28702         }
28703     },
28704
28705     
28706     moveProxy : function(parentNode, before){
28707         if(this.proxy){
28708             parentNode.insertBefore(this.proxy.dom, before);
28709         }
28710     }
28711 });
28712
28713
28714 Ext.Panel.DD = Ext.extend(Ext.dd.DragSource, {
28715     
28716     constructor : function(panel, cfg){
28717         this.panel = panel;
28718         this.dragData = {panel: panel};
28719         this.proxy = new Ext.dd.PanelProxy(panel, cfg);
28720         Ext.Panel.DD.superclass.constructor.call(this, panel.el, cfg);
28721         var h = panel.header,
28722             el = panel.body;
28723         if(h){
28724             this.setHandleElId(h.id);
28725             el = panel.header;
28726         }
28727         el.setStyle('cursor', 'move');
28728         this.scroll = false;        
28729     },
28730     
28731     showFrame: Ext.emptyFn,
28732     startDrag: Ext.emptyFn,
28733     b4StartDrag: function(x, y) {
28734         this.proxy.show();
28735     },
28736     b4MouseDown: function(e) {
28737         var x = e.getPageX(),
28738             y = e.getPageY();
28739         this.autoOffset(x, y);
28740     },
28741     onInitDrag : function(x, y){
28742         this.onStartDrag(x, y);
28743         return true;
28744     },
28745     createFrame : Ext.emptyFn,
28746     getDragEl : function(e){
28747         return this.proxy.ghost.dom;
28748     },
28749     endDrag : function(e){
28750         this.proxy.hide();
28751         this.panel.saveState();
28752     },
28753
28754     autoOffset : function(x, y) {
28755         x -= this.startPageX;
28756         y -= this.startPageY;
28757         this.setDelta(x, y);
28758     }
28759 });
28760 Ext.state.Provider = Ext.extend(Ext.util.Observable, {
28761     
28762     constructor : function(){
28763         
28764         this.addEvents("statechange");
28765         this.state = {};
28766         Ext.state.Provider.superclass.constructor.call(this);
28767     },
28768     
28769     
28770     get : function(name, defaultValue){
28771         return typeof this.state[name] == "undefined" ?
28772             defaultValue : this.state[name];
28773     },
28774
28775     
28776     clear : function(name){
28777         delete this.state[name];
28778         this.fireEvent("statechange", this, name, null);
28779     },
28780
28781     
28782     set : function(name, value){
28783         this.state[name] = value;
28784         this.fireEvent("statechange", this, name, value);
28785     },
28786
28787     
28788     decodeValue : function(cookie){
28789         
28790         var re = /^(a|n|d|b|s|o|e)\:(.*)$/,
28791             matches = re.exec(unescape(cookie)),
28792             all,
28793             type,
28794             v,
28795             kv;
28796         if(!matches || !matches[1]){
28797             return; 
28798         }
28799         type = matches[1];
28800         v = matches[2];
28801         switch(type){
28802             case 'e':
28803                 return null;
28804             case 'n':
28805                 return parseFloat(v);
28806             case 'd':
28807                 return new Date(Date.parse(v));
28808             case 'b':
28809                 return (v == '1');
28810             case 'a':
28811                 all = [];
28812                 if(v != ''){
28813                     Ext.each(v.split('^'), function(val){
28814                         all.push(this.decodeValue(val));
28815                     }, this);
28816                 }
28817                 return all;
28818            case 'o':
28819                 all = {};
28820                 if(v != ''){
28821                     Ext.each(v.split('^'), function(val){
28822                         kv = val.split('=');
28823                         all[kv[0]] = this.decodeValue(kv[1]);
28824                     }, this);
28825                 }
28826                 return all;
28827            default:
28828                 return v;
28829         }
28830     },
28831
28832     
28833     encodeValue : function(v){
28834         var enc,
28835             flat = '',
28836             i = 0,
28837             len,
28838             key;
28839         if(v == null){
28840             return 'e:1';    
28841         }else if(typeof v == 'number'){
28842             enc = 'n:' + v;
28843         }else if(typeof v == 'boolean'){
28844             enc = 'b:' + (v ? '1' : '0');
28845         }else if(Ext.isDate(v)){
28846             enc = 'd:' + v.toGMTString();
28847         }else if(Ext.isArray(v)){
28848             for(len = v.length; i < len; i++){
28849                 flat += this.encodeValue(v[i]);
28850                 if(i != len - 1){
28851                     flat += '^';
28852                 }
28853             }
28854             enc = 'a:' + flat;
28855         }else if(typeof v == 'object'){
28856             for(key in v){
28857                 if(typeof v[key] != 'function' && v[key] !== undefined){
28858                     flat += key + '=' + this.encodeValue(v[key]) + '^';
28859                 }
28860             }
28861             enc = 'o:' + flat.substring(0, flat.length-1);
28862         }else{
28863             enc = 's:' + v;
28864         }
28865         return escape(enc);
28866     }
28867 });
28868
28869 Ext.state.Manager = function(){
28870     var provider = new Ext.state.Provider();
28871
28872     return {
28873         
28874         setProvider : function(stateProvider){
28875             provider = stateProvider;
28876         },
28877
28878         
28879         get : function(key, defaultValue){
28880             return provider.get(key, defaultValue);
28881         },
28882
28883         
28884          set : function(key, value){
28885             provider.set(key, value);
28886         },
28887
28888         
28889         clear : function(key){
28890             provider.clear(key);
28891         },
28892
28893         
28894         getProvider : function(){
28895             return provider;
28896         }
28897     };
28898 }();
28899
28900 Ext.state.CookieProvider = Ext.extend(Ext.state.Provider, {
28901     
28902     constructor : function(config){
28903         Ext.state.CookieProvider.superclass.constructor.call(this);
28904         this.path = "/";
28905         this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); 
28906         this.domain = null;
28907         this.secure = false;
28908         Ext.apply(this, config);
28909         this.state = this.readCookies();
28910     },
28911     
28912     
28913     set : function(name, value){
28914         if(typeof value == "undefined" || value === null){
28915             this.clear(name);
28916             return;
28917         }
28918         this.setCookie(name, value);
28919         Ext.state.CookieProvider.superclass.set.call(this, name, value);
28920     },
28921
28922     
28923     clear : function(name){
28924         this.clearCookie(name);
28925         Ext.state.CookieProvider.superclass.clear.call(this, name);
28926     },
28927
28928     
28929     readCookies : function(){
28930         var cookies = {},
28931             c = document.cookie + ";",
28932             re = /\s?(.*?)=(.*?);/g,
28933             matches,
28934             name,
28935             value;
28936         while((matches = re.exec(c)) != null){
28937             name = matches[1];
28938             value = matches[2];
28939             if(name && name.substring(0,3) == "ys-"){
28940                 cookies[name.substr(3)] = this.decodeValue(value);
28941             }
28942         }
28943         return cookies;
28944     },
28945
28946     
28947     setCookie : function(name, value){
28948         document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
28949            ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
28950            ((this.path == null) ? "" : ("; path=" + this.path)) +
28951            ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
28952            ((this.secure == true) ? "; secure" : "");
28953     },
28954
28955     
28956     clearCookie : function(name){
28957         document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
28958            ((this.path == null) ? "" : ("; path=" + this.path)) +
28959            ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
28960            ((this.secure == true) ? "; secure" : "");
28961     }
28962 });
28963 Ext.DataView = Ext.extend(Ext.BoxComponent, {
28964     
28965     
28966     
28967     
28968     
28969     
28970     
28971     
28972     
28973     selectedClass : "x-view-selected",
28974     
28975     emptyText : "",
28976
28977     
28978     deferEmptyText: true,
28979     
28980     trackOver: false,
28981     
28982     
28983     blockRefresh: false,
28984
28985     
28986     last: false,
28987
28988     
28989     initComponent : function(){
28990         Ext.DataView.superclass.initComponent.call(this);
28991         if(Ext.isString(this.tpl) || Ext.isArray(this.tpl)){
28992             this.tpl = new Ext.XTemplate(this.tpl);
28993         }
28994
28995         this.addEvents(
28996             
28997             "beforeclick",
28998             
28999             "click",
29000             
29001             "mouseenter",
29002             
29003             "mouseleave",
29004             
29005             "containerclick",
29006             
29007             "dblclick",
29008             
29009             "contextmenu",
29010             
29011             "containercontextmenu",
29012             
29013             "selectionchange",
29014
29015             
29016             "beforeselect"
29017         );
29018
29019         this.store = Ext.StoreMgr.lookup(this.store);
29020         this.all = new Ext.CompositeElementLite();
29021         this.selected = new Ext.CompositeElementLite();
29022     },
29023
29024     
29025     afterRender : function(){
29026         Ext.DataView.superclass.afterRender.call(this);
29027
29028                 this.mon(this.getTemplateTarget(), {
29029             "click": this.onClick,
29030             "dblclick": this.onDblClick,
29031             "contextmenu": this.onContextMenu,
29032             scope:this
29033         });
29034
29035         if(this.overClass || this.trackOver){
29036             this.mon(this.getTemplateTarget(), {
29037                 "mouseover": this.onMouseOver,
29038                 "mouseout": this.onMouseOut,
29039                 scope:this
29040             });
29041         }
29042
29043         if(this.store){
29044             this.bindStore(this.store, true);
29045         }
29046     },
29047
29048     
29049     refresh : function() {
29050         this.clearSelections(false, true);
29051         var el = this.getTemplateTarget(),
29052             records = this.store.getRange();
29053             
29054         el.update('');
29055         if(records.length < 1){
29056             if(!this.deferEmptyText || this.hasSkippedEmptyText){
29057                 el.update(this.emptyText);
29058             }
29059             this.all.clear();
29060         }else{
29061             this.tpl.overwrite(el, this.collectData(records, 0));
29062             this.all.fill(Ext.query(this.itemSelector, el.dom));
29063             this.updateIndexes(0);
29064         }
29065         this.hasSkippedEmptyText = true;
29066     },
29067
29068     getTemplateTarget: function(){
29069         return this.el;
29070     },
29071
29072     
29073     prepareData : function(data){
29074         return data;
29075     },
29076
29077     
29078     collectData : function(records, startIndex){
29079         var r = [],
29080             i = 0,
29081             len = records.length;
29082         for(; i < len; i++){
29083             r[r.length] = this.prepareData(records[i].data, startIndex + i, records[i]);
29084         }
29085         return r;
29086     },
29087
29088     
29089     bufferRender : function(records, index){
29090         var div = document.createElement('div');
29091         this.tpl.overwrite(div, this.collectData(records, index));
29092         return Ext.query(this.itemSelector, div);
29093     },
29094
29095     
29096     onUpdate : function(ds, record){
29097         var index = this.store.indexOf(record);
29098         if(index > -1){
29099             var sel = this.isSelected(index),
29100                 original = this.all.elements[index],
29101                 node = this.bufferRender([record], index)[0];
29102
29103             this.all.replaceElement(index, node, true);
29104             if(sel){
29105                 this.selected.replaceElement(original, node);
29106                 this.all.item(index).addClass(this.selectedClass);
29107             }
29108             this.updateIndexes(index, index);
29109         }
29110     },
29111
29112     
29113     onAdd : function(ds, records, index){
29114         if(this.all.getCount() === 0){
29115             this.refresh();
29116             return;
29117         }
29118         var nodes = this.bufferRender(records, index), n, a = this.all.elements;
29119         if(index < this.all.getCount()){
29120             n = this.all.item(index).insertSibling(nodes, 'before', true);
29121             a.splice.apply(a, [index, 0].concat(nodes));
29122         }else{
29123             n = this.all.last().insertSibling(nodes, 'after', true);
29124             a.push.apply(a, nodes);
29125         }
29126         this.updateIndexes(index);
29127     },
29128
29129     
29130     onRemove : function(ds, record, index){
29131         this.deselect(index);
29132         this.all.removeElement(index, true);
29133         this.updateIndexes(index);
29134         if (this.store.getCount() === 0){
29135             this.refresh();
29136         }
29137     },
29138
29139     
29140     refreshNode : function(index){
29141         this.onUpdate(this.store, this.store.getAt(index));
29142     },
29143
29144     
29145     updateIndexes : function(startIndex, endIndex){
29146         var ns = this.all.elements;
29147         startIndex = startIndex || 0;
29148         endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length - 1));
29149         for(var i = startIndex; i <= endIndex; i++){
29150             ns[i].viewIndex = i;
29151         }
29152     },
29153     
29154     
29155     getStore : function(){
29156         return this.store;
29157     },
29158
29159     
29160     bindStore : function(store, initial){
29161         if(!initial && this.store){
29162             if(store !== this.store && this.store.autoDestroy){
29163                 this.store.destroy();
29164             }else{
29165                 this.store.un("beforeload", this.onBeforeLoad, this);
29166                 this.store.un("datachanged", this.onDataChanged, this);
29167                 this.store.un("add", this.onAdd, this);
29168                 this.store.un("remove", this.onRemove, this);
29169                 this.store.un("update", this.onUpdate, this);
29170                 this.store.un("clear", this.refresh, this);
29171             }
29172             if(!store){
29173                 this.store = null;
29174             }
29175         }
29176         if(store){
29177             store = Ext.StoreMgr.lookup(store);
29178             store.on({
29179                 scope: this,
29180                 beforeload: this.onBeforeLoad,
29181                 datachanged: this.onDataChanged,
29182                 add: this.onAdd,
29183                 remove: this.onRemove,
29184                 update: this.onUpdate,
29185                 clear: this.refresh
29186             });
29187         }
29188         this.store = store;
29189         if(store){
29190             this.refresh();
29191         }
29192     },
29193     
29194     
29195     onDataChanged: function() {
29196         if (this.blockRefresh !== true) {
29197             this.refresh.apply(this, arguments);
29198         }
29199     },
29200
29201     
29202     findItemFromChild : function(node){
29203         return Ext.fly(node).findParent(this.itemSelector, this.getTemplateTarget());
29204     },
29205
29206     
29207     onClick : function(e){
29208         var item = e.getTarget(this.itemSelector, this.getTemplateTarget()),
29209             index;
29210         if(item){
29211             index = this.indexOf(item);
29212             if(this.onItemClick(item, index, e) !== false){
29213                 this.fireEvent("click", this, index, item, e);
29214             }
29215         }else{
29216             if(this.fireEvent("containerclick", this, e) !== false){
29217                 this.onContainerClick(e);
29218             }
29219         }
29220     },
29221
29222     onContainerClick : function(e){
29223         this.clearSelections();
29224     },
29225
29226     
29227     onContextMenu : function(e){
29228         var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
29229         if(item){
29230             this.fireEvent("contextmenu", this, this.indexOf(item), item, e);
29231         }else{
29232             this.fireEvent("containercontextmenu", this, e);
29233         }
29234     },
29235
29236     
29237     onDblClick : function(e){
29238         var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
29239         if(item){
29240             this.fireEvent("dblclick", this, this.indexOf(item), item, e);
29241         }
29242     },
29243
29244     
29245     onMouseOver : function(e){
29246         var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
29247         if(item && item !== this.lastItem){
29248             this.lastItem = item;
29249             Ext.fly(item).addClass(this.overClass);
29250             this.fireEvent("mouseenter", this, this.indexOf(item), item, e);
29251         }
29252     },
29253
29254     
29255     onMouseOut : function(e){
29256         if(this.lastItem){
29257             if(!e.within(this.lastItem, true, true)){
29258                 Ext.fly(this.lastItem).removeClass(this.overClass);
29259                 this.fireEvent("mouseleave", this, this.indexOf(this.lastItem), this.lastItem, e);
29260                 delete this.lastItem;
29261             }
29262         }
29263     },
29264
29265     
29266     onItemClick : function(item, index, e){
29267         if(this.fireEvent("beforeclick", this, index, item, e) === false){
29268             return false;
29269         }
29270         if(this.multiSelect){
29271             this.doMultiSelection(item, index, e);
29272             e.preventDefault();
29273         }else if(this.singleSelect){
29274             this.doSingleSelection(item, index, e);
29275             e.preventDefault();
29276         }
29277         return true;
29278     },
29279
29280     
29281     doSingleSelection : function(item, index, e){
29282         if(e.ctrlKey && this.isSelected(index)){
29283             this.deselect(index);
29284         }else{
29285             this.select(index, false);
29286         }
29287     },
29288
29289     
29290     doMultiSelection : function(item, index, e){
29291         if(e.shiftKey && this.last !== false){
29292             var last = this.last;
29293             this.selectRange(last, index, e.ctrlKey);
29294             this.last = last; 
29295         }else{
29296             if((e.ctrlKey||this.simpleSelect) && this.isSelected(index)){
29297                 this.deselect(index);
29298             }else{
29299                 this.select(index, e.ctrlKey || e.shiftKey || this.simpleSelect);
29300             }
29301         }
29302     },
29303
29304     
29305     getSelectionCount : function(){
29306         return this.selected.getCount();
29307     },
29308
29309     
29310     getSelectedNodes : function(){
29311         return this.selected.elements;
29312     },
29313
29314     
29315     getSelectedIndexes : function(){
29316         var indexes = [], 
29317             selected = this.selected.elements,
29318             i = 0,
29319             len = selected.length;
29320             
29321         for(; i < len; i++){
29322             indexes.push(selected[i].viewIndex);
29323         }
29324         return indexes;
29325     },
29326
29327     
29328     getSelectedRecords : function(){
29329         return this.getRecords(this.selected.elements);
29330     },
29331
29332     
29333     getRecords : function(nodes){
29334         var records = [], 
29335             i = 0,
29336             len = nodes.length;
29337             
29338         for(; i < len; i++){
29339             records[records.length] = this.store.getAt(nodes[i].viewIndex);
29340         }
29341         return records;
29342     },
29343
29344     
29345     getRecord : function(node){
29346         return this.store.getAt(node.viewIndex);
29347     },
29348
29349     
29350     clearSelections : function(suppressEvent, skipUpdate){
29351         if((this.multiSelect || this.singleSelect) && this.selected.getCount() > 0){
29352             if(!skipUpdate){
29353                 this.selected.removeClass(this.selectedClass);
29354             }
29355             this.selected.clear();
29356             this.last = false;
29357             if(!suppressEvent){
29358                 this.fireEvent("selectionchange", this, this.selected.elements);
29359             }
29360         }
29361     },
29362
29363     
29364     isSelected : function(node){
29365         return this.selected.contains(this.getNode(node));
29366     },
29367
29368     
29369     deselect : function(node){
29370         if(this.isSelected(node)){
29371             node = this.getNode(node);
29372             this.selected.removeElement(node);
29373             if(this.last == node.viewIndex){
29374                 this.last = false;
29375             }
29376             Ext.fly(node).removeClass(this.selectedClass);
29377             this.fireEvent("selectionchange", this, this.selected.elements);
29378         }
29379     },
29380
29381     
29382     select : function(nodeInfo, keepExisting, suppressEvent){
29383         if(Ext.isArray(nodeInfo)){
29384             if(!keepExisting){
29385                 this.clearSelections(true);
29386             }
29387             for(var i = 0, len = nodeInfo.length; i < len; i++){
29388                 this.select(nodeInfo[i], true, true);
29389             }
29390             if(!suppressEvent){
29391                 this.fireEvent("selectionchange", this, this.selected.elements);
29392             }
29393         } else{
29394             var node = this.getNode(nodeInfo);
29395             if(!keepExisting){
29396                 this.clearSelections(true);
29397             }
29398             if(node && !this.isSelected(node)){
29399                 if(this.fireEvent("beforeselect", this, node, this.selected.elements) !== false){
29400                     Ext.fly(node).addClass(this.selectedClass);
29401                     this.selected.add(node);
29402                     this.last = node.viewIndex;
29403                     if(!suppressEvent){
29404                         this.fireEvent("selectionchange", this, this.selected.elements);
29405                     }
29406                 }
29407             }
29408         }
29409     },
29410
29411     
29412     selectRange : function(start, end, keepExisting){
29413         if(!keepExisting){
29414             this.clearSelections(true);
29415         }
29416         this.select(this.getNodes(start, end), true);
29417     },
29418
29419     
29420     getNode : function(nodeInfo){
29421         if(Ext.isString(nodeInfo)){
29422             return document.getElementById(nodeInfo);
29423         }else if(Ext.isNumber(nodeInfo)){
29424             return this.all.elements[nodeInfo];
29425         }else if(nodeInfo instanceof Ext.data.Record){
29426             var idx = this.store.indexOf(nodeInfo);
29427             return this.all.elements[idx];
29428         }
29429         return nodeInfo;
29430     },
29431
29432     
29433     getNodes : function(start, end){
29434         var ns = this.all.elements,
29435             nodes = [],
29436             i;
29437             
29438         start = start || 0;
29439         end = !Ext.isDefined(end) ? Math.max(ns.length - 1, 0) : end;
29440         if(start <= end){
29441             for(i = start; i <= end && ns[i]; i++){
29442                 nodes.push(ns[i]);
29443             }
29444         } else{
29445             for(i = start; i >= end && ns[i]; i--){
29446                 nodes.push(ns[i]);
29447             }
29448         }
29449         return nodes;
29450     },
29451
29452     
29453     indexOf : function(node){
29454         node = this.getNode(node);
29455         if(Ext.isNumber(node.viewIndex)){
29456             return node.viewIndex;
29457         }
29458         return this.all.indexOf(node);
29459     },
29460
29461     
29462     onBeforeLoad : function(){
29463         if(this.loadingText){
29464             this.clearSelections(false, true);
29465             this.getTemplateTarget().update('<div class="loading-indicator">'+this.loadingText+'</div>');
29466             this.all.clear();
29467         }
29468     },
29469
29470     onDestroy : function(){
29471         this.all.clear();
29472         this.selected.clear();
29473         Ext.DataView.superclass.onDestroy.call(this);
29474         this.bindStore(null);
29475     }
29476 });
29477
29478
29479 Ext.DataView.prototype.setStore = Ext.DataView.prototype.bindStore;
29480
29481 Ext.reg('dataview', Ext.DataView);
29482
29483 Ext.list.ListView = Ext.extend(Ext.DataView, {
29484     
29485     
29486     
29487     itemSelector: 'dl',
29488     
29489     selectedClass:'x-list-selected',
29490     
29491     overClass:'x-list-over',
29492     
29493     
29494     scrollOffset : undefined,
29495     
29496     columnResize: true,
29497     
29498     
29499     columnSort: true,
29500     
29501
29502     
29503     maxColumnWidth: Ext.isIE ? 99 : 100,
29504
29505     initComponent : function(){
29506         if(this.columnResize){
29507             this.colResizer = new Ext.list.ColumnResizer(this.colResizer);
29508             this.colResizer.init(this);
29509         }
29510         if(this.columnSort){
29511             this.colSorter = new Ext.list.Sorter(this.columnSort);
29512             this.colSorter.init(this);
29513         }
29514         if(!this.internalTpl){
29515             this.internalTpl = new Ext.XTemplate(
29516                 '<div class="x-list-header"><div class="x-list-header-inner">',
29517                     '<tpl for="columns">',
29518                     '<div style="width:{[values.width*100]}%;text-align:{align};"><em unselectable="on" id="',this.id, '-xlhd-{#}">',
29519                         '{header}',
29520                     '</em></div>',
29521                     '</tpl>',
29522                     '<div class="x-clear"></div>',
29523                 '</div></div>',
29524                 '<div class="x-list-body"><div class="x-list-body-inner">',
29525                 '</div></div>'
29526             );
29527         }
29528         if(!this.tpl){
29529             this.tpl = new Ext.XTemplate(
29530                 '<tpl for="rows">',
29531                     '<dl>',
29532                         '<tpl for="parent.columns">',
29533                         '<dt style="width:{[values.width*100]}%;text-align:{align};">',
29534                         '<em unselectable="on"<tpl if="cls"> class="{cls}</tpl>">',
29535                             '{[values.tpl.apply(parent)]}',
29536                         '</em></dt>',
29537                         '</tpl>',
29538                         '<div class="x-clear"></div>',
29539                     '</dl>',
29540                 '</tpl>'
29541             );
29542         };
29543
29544         var cs = this.columns,
29545             allocatedWidth = 0,
29546             colsWithWidth = 0,
29547             len = cs.length,
29548             columns = [];
29549
29550         for(var i = 0; i < len; i++){
29551             var c = cs[i];
29552             if(!c.isColumn) {
29553                 c.xtype = c.xtype ? (/^lv/.test(c.xtype) ? c.xtype : 'lv' + c.xtype) : 'lvcolumn';
29554                 c = Ext.create(c);
29555             }
29556             if(c.width) {
29557                 allocatedWidth += c.width*100;
29558                 if(allocatedWidth > this.maxColumnWidth){
29559                     c.width -= (allocatedWidth - this.maxColumnWidth) / 100;
29560                 }
29561                 colsWithWidth++;
29562             }
29563             columns.push(c);
29564         }
29565
29566         cs = this.columns = columns;
29567
29568         
29569         if(colsWithWidth < len){
29570             var remaining = len - colsWithWidth;
29571             if(allocatedWidth < this.maxColumnWidth){
29572                 var perCol = ((this.maxColumnWidth-allocatedWidth) / remaining)/100;
29573                 for(var j = 0; j < len; j++){
29574                     var c = cs[j];
29575                     if(!c.width){
29576                         c.width = perCol;
29577                     }
29578                 }
29579             }
29580         }
29581         Ext.list.ListView.superclass.initComponent.call(this);
29582     },
29583
29584     onRender : function(){
29585         this.autoEl = {
29586             cls: 'x-list-wrap'
29587         };
29588         Ext.list.ListView.superclass.onRender.apply(this, arguments);
29589
29590         this.internalTpl.overwrite(this.el, {columns: this.columns});
29591
29592         this.innerBody = Ext.get(this.el.dom.childNodes[1].firstChild);
29593         this.innerHd = Ext.get(this.el.dom.firstChild.firstChild);
29594
29595         if(this.hideHeaders){
29596             this.el.dom.firstChild.style.display = 'none';
29597         }
29598     },
29599
29600     getTemplateTarget : function(){
29601         return this.innerBody;
29602     },
29603
29604     
29605     collectData : function(){
29606         var rs = Ext.list.ListView.superclass.collectData.apply(this, arguments);
29607         return {
29608             columns: this.columns,
29609             rows: rs
29610         };
29611     },
29612
29613     verifyInternalSize : function(){
29614         if(this.lastSize){
29615             this.onResize(this.lastSize.width, this.lastSize.height);
29616         }
29617     },
29618
29619     
29620     onResize : function(w, h){
29621         var body = this.innerBody.dom,
29622             header = this.innerHd.dom,
29623             scrollWidth = w - Ext.num(this.scrollOffset, Ext.getScrollBarWidth()) + 'px',
29624             parentNode;
29625             
29626         if(!body){
29627             return;
29628         }
29629         parentNode = body.parentNode;
29630         if(Ext.isNumber(w)){
29631             if(this.reserveScrollOffset || ((parentNode.offsetWidth - parentNode.clientWidth) > 10)){
29632                 body.style.width = scrollWidth;
29633                 header.style.width = scrollWidth;
29634             }else{
29635                 body.style.width = w + 'px';
29636                 header.style.width = w + 'px';
29637                 setTimeout(function(){
29638                     if((parentNode.offsetWidth - parentNode.clientWidth) > 10){
29639                         body.style.width = scrollWidth;
29640                         header.style.width = scrollWidth;
29641                     }
29642                 }, 10);
29643             }
29644         }
29645         if(Ext.isNumber(h)){
29646             parentNode.style.height = Math.max(0, h - header.parentNode.offsetHeight) + 'px';
29647         }
29648     },
29649
29650     updateIndexes : function(){
29651         Ext.list.ListView.superclass.updateIndexes.apply(this, arguments);
29652         this.verifyInternalSize();
29653     },
29654
29655     findHeaderIndex : function(header){
29656         header = header.dom || header;
29657         var parentNode = header.parentNode, 
29658             children = parentNode.parentNode.childNodes,
29659             i = 0,
29660             c;
29661         for(; c = children[i]; i++){
29662             if(c == parentNode){
29663                 return i;
29664             }
29665         }
29666         return -1;
29667     },
29668
29669     setHdWidths : function(){
29670         var els = this.innerHd.dom.getElementsByTagName('div'),
29671             i = 0,
29672             columns = this.columns,
29673             len = columns.length;
29674             
29675         for(; i < len; i++){
29676             els[i].style.width = (columns[i].width*100) + '%';
29677         }
29678     }
29679 });
29680
29681 Ext.reg('listview', Ext.list.ListView);
29682
29683
29684 Ext.ListView = Ext.list.ListView;
29685 Ext.list.Column = Ext.extend(Object, {
29686     
29687     isColumn: true,
29688     
29689             
29690     align: 'left',
29691         
29692     header: '',
29693     
29694         
29695     width: null,
29696
29697     
29698     cls: '',
29699     
29700     
29701
29702     
29703     
29704     constructor : function(c){
29705         if(!c.tpl){
29706             c.tpl = new Ext.XTemplate('{' + c.dataIndex + '}');
29707         }
29708         else if(Ext.isString(c.tpl)){
29709             c.tpl = new Ext.XTemplate(c.tpl);
29710         }
29711         
29712         Ext.apply(this, c);
29713     }
29714 });
29715
29716 Ext.reg('lvcolumn', Ext.list.Column);
29717
29718
29719 Ext.list.NumberColumn = Ext.extend(Ext.list.Column, {
29720         
29721     format: '0,000.00',
29722     
29723     constructor : function(c) {
29724         c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':number("' + (c.format || this.format) + '")}');       
29725         Ext.list.NumberColumn.superclass.constructor.call(this, c);
29726     }
29727 });
29728
29729 Ext.reg('lvnumbercolumn', Ext.list.NumberColumn);
29730
29731
29732 Ext.list.DateColumn = Ext.extend(Ext.list.Column, {
29733     format: 'm/d/Y',
29734     constructor : function(c) {
29735         c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':date("' + (c.format || this.format) + '")}');      
29736         Ext.list.DateColumn.superclass.constructor.call(this, c);
29737     }
29738 });
29739 Ext.reg('lvdatecolumn', Ext.list.DateColumn);
29740
29741
29742 Ext.list.BooleanColumn = Ext.extend(Ext.list.Column, {
29743     
29744     trueText: 'true',
29745     
29746     falseText: 'false',
29747     
29748     undefinedText: '&#160;',
29749     
29750     constructor : function(c) {
29751         c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':this.format}');
29752         
29753         var t = this.trueText, f = this.falseText, u = this.undefinedText;
29754         c.tpl.format = function(v){
29755             if(v === undefined){
29756                 return u;
29757             }
29758             if(!v || v === 'false'){
29759                 return f;
29760             }
29761             return t;
29762         };
29763         
29764         Ext.list.DateColumn.superclass.constructor.call(this, c);
29765     }
29766 });
29767
29768 Ext.reg('lvbooleancolumn', Ext.list.BooleanColumn);
29769 Ext.list.ColumnResizer = Ext.extend(Ext.util.Observable, {
29770     
29771     minPct: .05,
29772
29773     constructor: function(config){
29774         Ext.apply(this, config);
29775         Ext.list.ColumnResizer.superclass.constructor.call(this);
29776     },
29777     init : function(listView){
29778         this.view = listView;
29779         listView.on('render', this.initEvents, this);
29780     },
29781
29782     initEvents : function(view){
29783         view.mon(view.innerHd, 'mousemove', this.handleHdMove, this);
29784         this.tracker = new Ext.dd.DragTracker({
29785             onBeforeStart: this.onBeforeStart.createDelegate(this),
29786             onStart: this.onStart.createDelegate(this),
29787             onDrag: this.onDrag.createDelegate(this),
29788             onEnd: this.onEnd.createDelegate(this),
29789             tolerance: 3,
29790             autoStart: 300
29791         });
29792         this.tracker.initEl(view.innerHd);
29793         view.on('beforedestroy', this.tracker.destroy, this.tracker);
29794     },
29795
29796     handleHdMove : function(e, t){
29797         var handleWidth = 5,
29798             x = e.getPageX(),
29799             header = e.getTarget('em', 3, true);
29800         if(header){
29801             var region = header.getRegion(),
29802                 style = header.dom.style,
29803                 parentNode = header.dom.parentNode;
29804
29805             if(x - region.left <= handleWidth && parentNode != parentNode.parentNode.firstChild){
29806                 this.activeHd = Ext.get(parentNode.previousSibling.firstChild);
29807                 style.cursor = Ext.isWebKit ? 'e-resize' : 'col-resize';
29808             } else if(region.right - x <= handleWidth && parentNode != parentNode.parentNode.lastChild.previousSibling){
29809                 this.activeHd = header;
29810                 style.cursor = Ext.isWebKit ? 'w-resize' : 'col-resize';
29811             } else{
29812                 delete this.activeHd;
29813                 style.cursor = '';
29814             }
29815         }
29816     },
29817
29818     onBeforeStart : function(e){
29819         this.dragHd = this.activeHd;
29820         return !!this.dragHd;
29821     },
29822
29823     onStart: function(e){
29824         
29825         var me = this,
29826             view = me.view,
29827             dragHeader = me.dragHd,
29828             x = me.tracker.getXY()[0];            
29829         
29830         me.proxy = view.el.createChild({cls:'x-list-resizer'});
29831         me.dragX = dragHeader.getX();
29832         me.headerIndex = view.findHeaderIndex(dragHeader);
29833         
29834         me.headersDisabled = view.disableHeaders;
29835         view.disableHeaders = true;
29836         
29837         me.proxy.setHeight(view.el.getHeight());
29838         me.proxy.setX(me.dragX);
29839         me.proxy.setWidth(x - me.dragX);
29840         
29841         this.setBoundaries();
29842         
29843     },
29844     
29845     
29846     setBoundaries: function(relativeX){
29847         var view = this.view,
29848             headerIndex = this.headerIndex,
29849             width = view.innerHd.getWidth(),
29850             relativeX = view.innerHd.getX(),
29851             minWidth = Math.ceil(width * this.minPct),
29852             maxWidth = width - minWidth,
29853             numColumns = view.columns.length,
29854             headers = view.innerHd.select('em', true),
29855             minX = minWidth + relativeX,
29856             maxX = maxWidth + relativeX,
29857             header;
29858           
29859         if (numColumns == 2) {
29860             this.minX = minX;
29861             this.maxX = maxX;
29862         }else{
29863             header = headers.item(headerIndex + 2);
29864             this.minX = headers.item(headerIndex).getX() + minWidth;
29865             this.maxX = header ? header.getX() - minWidth : maxX;
29866             if (headerIndex == 0) {
29867                 
29868                 this.minX = minX;
29869             } else if (headerIndex == numColumns - 2) {
29870                 
29871                 this.maxX = maxX;
29872             }
29873         }
29874     },
29875
29876     onDrag: function(e){
29877         var me = this,
29878             cursorX = me.tracker.getXY()[0].constrain(me.minX, me.maxX);
29879             
29880         me.proxy.setWidth(cursorX - this.dragX);
29881     },
29882
29883     onEnd: function(e){
29884         
29885         var newWidth = this.proxy.getWidth(),
29886             index = this.headerIndex,
29887             view = this.view,
29888             columns = view.columns,
29889             width = view.innerHd.getWidth(),
29890             newPercent = Math.ceil(newWidth * view.maxColumnWidth / width) / 100,
29891             disabled = this.headersDisabled,
29892             headerCol = columns[index],
29893             otherCol = columns[index + 1],
29894             totalPercent = headerCol.width + otherCol.width;
29895
29896         this.proxy.remove();
29897
29898         headerCol.width = newPercent;
29899         otherCol.width = totalPercent - newPercent;
29900       
29901         delete this.dragHd;
29902         view.setHdWidths();
29903         view.refresh();
29904         
29905         setTimeout(function(){
29906             view.disableHeaders = disabled;
29907         }, 100);
29908     }
29909 });
29910
29911
29912 Ext.ListView.ColumnResizer = Ext.list.ColumnResizer;
29913 Ext.list.Sorter = Ext.extend(Ext.util.Observable, {
29914     
29915     sortClasses : ["sort-asc", "sort-desc"],
29916
29917     constructor: function(config){
29918         Ext.apply(this, config);
29919         Ext.list.Sorter.superclass.constructor.call(this);
29920     },
29921
29922     init : function(listView){
29923         this.view = listView;
29924         listView.on('render', this.initEvents, this);
29925     },
29926
29927     initEvents : function(view){
29928         view.mon(view.innerHd, 'click', this.onHdClick, this);
29929         view.innerHd.setStyle('cursor', 'pointer');
29930         view.mon(view.store, 'datachanged', this.updateSortState, this);
29931         this.updateSortState.defer(10, this, [view.store]);
29932     },
29933
29934     updateSortState : function(store){
29935         var state = store.getSortState();
29936         if(!state){
29937             return;
29938         }
29939         this.sortState = state;
29940         var cs = this.view.columns, sortColumn = -1;
29941         for(var i = 0, len = cs.length; i < len; i++){
29942             if(cs[i].dataIndex == state.field){
29943                 sortColumn = i;
29944                 break;
29945             }
29946         }
29947         if(sortColumn != -1){
29948             var sortDir = state.direction;
29949             this.updateSortIcon(sortColumn, sortDir);
29950         }
29951     },
29952
29953     updateSortIcon : function(col, dir){
29954         var sc = this.sortClasses;
29955         var hds = this.view.innerHd.select('em').removeClass(sc);
29956         hds.item(col).addClass(sc[dir == "DESC" ? 1 : 0]);
29957     },
29958
29959     onHdClick : function(e){
29960         var hd = e.getTarget('em', 3);
29961         if(hd && !this.view.disableHeaders){
29962             var index = this.view.findHeaderIndex(hd);
29963             this.view.store.sort(this.view.columns[index].dataIndex);
29964         }
29965     }
29966 });
29967
29968
29969 Ext.ListView.Sorter = Ext.list.Sorter;
29970 Ext.TabPanel = Ext.extend(Ext.Panel,  {
29971     
29972     
29973     
29974     deferredRender : true,
29975     
29976     tabWidth : 120,
29977     
29978     minTabWidth : 30,
29979     
29980     resizeTabs : false,
29981     
29982     enableTabScroll : false,
29983     
29984     scrollIncrement : 0,
29985     
29986     scrollRepeatInterval : 400,
29987     
29988     scrollDuration : 0.35,
29989     
29990     animScroll : true,
29991     
29992     tabPosition : 'top',
29993     
29994     baseCls : 'x-tab-panel',
29995     
29996     autoTabs : false,
29997     
29998     autoTabSelector : 'div.x-tab',
29999     
30000     activeTab : undefined,
30001     
30002     tabMargin : 2,
30003     
30004     plain : false,
30005     
30006     wheelIncrement : 20,
30007
30008     
30009     idDelimiter : '__',
30010
30011     
30012     itemCls : 'x-tab-item',
30013
30014     
30015     elements : 'body',
30016     headerAsText : false,
30017     frame : false,
30018     hideBorders :true,
30019
30020     
30021     initComponent : function(){
30022         this.frame = false;
30023         Ext.TabPanel.superclass.initComponent.call(this);
30024         this.addEvents(
30025             
30026             'beforetabchange',
30027             
30028             'tabchange',
30029             
30030             'contextmenu'
30031         );
30032         
30033         this.setLayout(new Ext.layout.CardLayout(Ext.apply({
30034             layoutOnCardChange: this.layoutOnTabChange,
30035             deferredRender: this.deferredRender
30036         }, this.layoutConfig)));
30037
30038         if(this.tabPosition == 'top'){
30039             this.elements += ',header';
30040             this.stripTarget = 'header';
30041         }else {
30042             this.elements += ',footer';
30043             this.stripTarget = 'footer';
30044         }
30045         if(!this.stack){
30046             this.stack = Ext.TabPanel.AccessStack();
30047         }
30048         this.initItems();
30049     },
30050
30051     
30052     onRender : function(ct, position){
30053         Ext.TabPanel.superclass.onRender.call(this, ct, position);
30054
30055         if(this.plain){
30056             var pos = this.tabPosition == 'top' ? 'header' : 'footer';
30057             this[pos].addClass('x-tab-panel-'+pos+'-plain');
30058         }
30059
30060         var st = this[this.stripTarget];
30061
30062         this.stripWrap = st.createChild({cls:'x-tab-strip-wrap', cn:{
30063             tag:'ul', cls:'x-tab-strip x-tab-strip-'+this.tabPosition}});
30064
30065         var beforeEl = (this.tabPosition=='bottom' ? this.stripWrap : null);
30066         st.createChild({cls:'x-tab-strip-spacer'}, beforeEl);
30067         this.strip = new Ext.Element(this.stripWrap.dom.firstChild);
30068
30069         
30070         this.edge = this.strip.createChild({tag:'li', cls:'x-tab-edge', cn: [{tag: 'span', cls: 'x-tab-strip-text', cn: '&#160;'}]});
30071         this.strip.createChild({cls:'x-clear'});
30072
30073         this.body.addClass('x-tab-panel-body-'+this.tabPosition);
30074
30075         
30076         if(!this.itemTpl){
30077             var tt = new Ext.Template(
30078                  '<li class="{cls}" id="{id}"><a class="x-tab-strip-close"></a>',
30079                  '<a class="x-tab-right" href="#"><em class="x-tab-left">',
30080                  '<span class="x-tab-strip-inner"><span class="x-tab-strip-text {iconCls}">{text}</span></span>',
30081                  '</em></a></li>'
30082             );
30083             tt.disableFormats = true;
30084             tt.compile();
30085             Ext.TabPanel.prototype.itemTpl = tt;
30086         }
30087
30088         this.items.each(this.initTab, this);
30089     },
30090
30091     
30092     afterRender : function(){
30093         Ext.TabPanel.superclass.afterRender.call(this);
30094         if(this.autoTabs){
30095             this.readTabs(false);
30096         }
30097         if(this.activeTab !== undefined){
30098             var item = Ext.isObject(this.activeTab) ? this.activeTab : this.items.get(this.activeTab);
30099             delete this.activeTab;
30100             this.setActiveTab(item);
30101         }
30102     },
30103
30104     
30105     initEvents : function(){
30106         Ext.TabPanel.superclass.initEvents.call(this);
30107         this.mon(this.strip, {
30108             scope: this,
30109             mousedown: this.onStripMouseDown,
30110             contextmenu: this.onStripContextMenu
30111         });
30112         if(this.enableTabScroll){
30113             this.mon(this.strip, 'mousewheel', this.onWheel, this);
30114         }
30115     },
30116
30117     
30118     findTargets : function(e){
30119         var item = null,
30120             itemEl = e.getTarget('li:not(.x-tab-edge)', this.strip);
30121
30122         if(itemEl){
30123             item = this.getComponent(itemEl.id.split(this.idDelimiter)[1]);
30124             if(item.disabled){
30125                 return {
30126                     close : null,
30127                     item : null,
30128                     el : null
30129                 };
30130             }
30131         }
30132         return {
30133             close : e.getTarget('.x-tab-strip-close', this.strip),
30134             item : item,
30135             el : itemEl
30136         };
30137     },
30138
30139     
30140     onStripMouseDown : function(e){
30141         if(e.button !== 0){
30142             return;
30143         }
30144         e.preventDefault();
30145         var t = this.findTargets(e);
30146         if(t.close){
30147             if (t.item.fireEvent('beforeclose', t.item) !== false) {
30148                 t.item.fireEvent('close', t.item);
30149                 this.remove(t.item);
30150             }
30151             return;
30152         }
30153         if(t.item && t.item != this.activeTab){
30154             this.setActiveTab(t.item);
30155         }
30156     },
30157
30158     
30159     onStripContextMenu : function(e){
30160         e.preventDefault();
30161         var t = this.findTargets(e);
30162         if(t.item){
30163             this.fireEvent('contextmenu', this, t.item, e);
30164         }
30165     },
30166
30167     
30168     readTabs : function(removeExisting){
30169         if(removeExisting === true){
30170             this.items.each(function(item){
30171                 this.remove(item);
30172             }, this);
30173         }
30174         var tabs = this.el.query(this.autoTabSelector);
30175         for(var i = 0, len = tabs.length; i < len; i++){
30176             var tab = tabs[i],
30177                 title = tab.getAttribute('title');
30178             tab.removeAttribute('title');
30179             this.add({
30180                 title: title,
30181                 contentEl: tab
30182             });
30183         }
30184     },
30185
30186     
30187     initTab : function(item, index){
30188         var before = this.strip.dom.childNodes[index],
30189             p = this.getTemplateArgs(item),
30190             el = before ?
30191                  this.itemTpl.insertBefore(before, p) :
30192                  this.itemTpl.append(this.strip, p),
30193             cls = 'x-tab-strip-over',
30194             tabEl = Ext.get(el);
30195
30196         tabEl.hover(function(){
30197             if(!item.disabled){
30198                 tabEl.addClass(cls);
30199             }
30200         }, function(){
30201             tabEl.removeClass(cls);
30202         });
30203
30204         if(item.tabTip){
30205             tabEl.child('span.x-tab-strip-text', true).qtip = item.tabTip;
30206         }
30207         item.tabEl = el;
30208
30209         
30210         tabEl.select('a').on('click', function(e){
30211             if(!e.getPageX()){
30212                 this.onStripMouseDown(e);
30213             }
30214         }, this, {preventDefault: true});
30215
30216         item.on({
30217             scope: this,
30218             disable: this.onItemDisabled,
30219             enable: this.onItemEnabled,
30220             titlechange: this.onItemTitleChanged,
30221             iconchange: this.onItemIconChanged,
30222             beforeshow: this.onBeforeShowItem
30223         });
30224     },
30225
30226
30227
30228     
30229     getTemplateArgs : function(item) {
30230         var cls = item.closable ? 'x-tab-strip-closable' : '';
30231         if(item.disabled){
30232             cls += ' x-item-disabled';
30233         }
30234         if(item.iconCls){
30235             cls += ' x-tab-with-icon';
30236         }
30237         if(item.tabCls){
30238             cls += ' ' + item.tabCls;
30239         }
30240
30241         return {
30242             id: this.id + this.idDelimiter + item.getItemId(),
30243             text: item.title,
30244             cls: cls,
30245             iconCls: item.iconCls || ''
30246         };
30247     },
30248
30249     
30250     onAdd : function(c){
30251         Ext.TabPanel.superclass.onAdd.call(this, c);
30252         if(this.rendered){
30253             var items = this.items;
30254             this.initTab(c, items.indexOf(c));
30255             this.delegateUpdates();
30256         }
30257     },
30258
30259     
30260     onBeforeAdd : function(item){
30261         var existing = item.events ? (this.items.containsKey(item.getItemId()) ? item : null) : this.items.get(item);
30262         if(existing){
30263             this.setActiveTab(item);
30264             return false;
30265         }
30266         Ext.TabPanel.superclass.onBeforeAdd.apply(this, arguments);
30267         var es = item.elements;
30268         item.elements = es ? es.replace(',header', '') : es;
30269         item.border = (item.border === true);
30270     },
30271
30272     
30273     onRemove : function(c){
30274         var te = Ext.get(c.tabEl);
30275         
30276         if(te){
30277             te.select('a').removeAllListeners();
30278             Ext.destroy(te);
30279         }
30280         Ext.TabPanel.superclass.onRemove.call(this, c);
30281         this.stack.remove(c);
30282         delete c.tabEl;
30283         c.un('disable', this.onItemDisabled, this);
30284         c.un('enable', this.onItemEnabled, this);
30285         c.un('titlechange', this.onItemTitleChanged, this);
30286         c.un('iconchange', this.onItemIconChanged, this);
30287         c.un('beforeshow', this.onBeforeShowItem, this);
30288         if(c == this.activeTab){
30289             var next = this.stack.next();
30290             if(next){
30291                 this.setActiveTab(next);
30292             }else if(this.items.getCount() > 0){
30293                 this.setActiveTab(0);
30294             }else{
30295                 this.setActiveTab(null);
30296             }
30297         }
30298         if(!this.destroying){
30299             this.delegateUpdates();
30300         }
30301     },
30302
30303     
30304     onBeforeShowItem : function(item){
30305         if(item != this.activeTab){
30306             this.setActiveTab(item);
30307             return false;
30308         }
30309     },
30310
30311     
30312     onItemDisabled : function(item){
30313         var el = this.getTabEl(item);
30314         if(el){
30315             Ext.fly(el).addClass('x-item-disabled');
30316         }
30317         this.stack.remove(item);
30318     },
30319
30320     
30321     onItemEnabled : function(item){
30322         var el = this.getTabEl(item);
30323         if(el){
30324             Ext.fly(el).removeClass('x-item-disabled');
30325         }
30326     },
30327
30328     
30329     onItemTitleChanged : function(item){
30330         var el = this.getTabEl(item);
30331         if(el){
30332             Ext.fly(el).child('span.x-tab-strip-text', true).innerHTML = item.title;
30333         }
30334     },
30335
30336     
30337     onItemIconChanged : function(item, iconCls, oldCls){
30338         var el = this.getTabEl(item);
30339         if(el){
30340             el = Ext.get(el);
30341             el.child('span.x-tab-strip-text').replaceClass(oldCls, iconCls);
30342             el[Ext.isEmpty(iconCls) ? 'removeClass' : 'addClass']('x-tab-with-icon');
30343         }
30344     },
30345
30346     
30347     getTabEl : function(item){
30348         var c = this.getComponent(item);
30349         return c ? c.tabEl : null;
30350     },
30351
30352     
30353     onResize : function(){
30354         Ext.TabPanel.superclass.onResize.apply(this, arguments);
30355         this.delegateUpdates();
30356     },
30357
30358     
30359     beginUpdate : function(){
30360         this.suspendUpdates = true;
30361     },
30362
30363     
30364     endUpdate : function(){
30365         this.suspendUpdates = false;
30366         this.delegateUpdates();
30367     },
30368
30369     
30370     hideTabStripItem : function(item){
30371         item = this.getComponent(item);
30372         var el = this.getTabEl(item);
30373         if(el){
30374             el.style.display = 'none';
30375             this.delegateUpdates();
30376         }
30377         this.stack.remove(item);
30378     },
30379
30380     
30381     unhideTabStripItem : function(item){
30382         item = this.getComponent(item);
30383         var el = this.getTabEl(item);
30384         if(el){
30385             el.style.display = '';
30386             this.delegateUpdates();
30387         }
30388     },
30389
30390     
30391     delegateUpdates : function(){
30392         var rendered = this.rendered;
30393         if(this.suspendUpdates){
30394             return;
30395         }
30396         if(this.resizeTabs && rendered){
30397             this.autoSizeTabs();
30398         }
30399         if(this.enableTabScroll && rendered){
30400             this.autoScrollTabs();
30401         }
30402     },
30403
30404     
30405     autoSizeTabs : function(){
30406         var count = this.items.length,
30407             ce = this.tabPosition != 'bottom' ? 'header' : 'footer',
30408             ow = this[ce].dom.offsetWidth,
30409             aw = this[ce].dom.clientWidth;
30410
30411         if(!this.resizeTabs || count < 1 || !aw){ 
30412             return;
30413         }
30414
30415         var each = Math.max(Math.min(Math.floor((aw-4) / count) - this.tabMargin, this.tabWidth), this.minTabWidth); 
30416         this.lastTabWidth = each;
30417         var lis = this.strip.query('li:not(.x-tab-edge)');
30418         for(var i = 0, len = lis.length; i < len; i++) {
30419             var li = lis[i],
30420                 inner = Ext.fly(li).child('.x-tab-strip-inner', true),
30421                 tw = li.offsetWidth,
30422                 iw = inner.offsetWidth;
30423             inner.style.width = (each - (tw-iw)) + 'px';
30424         }
30425     },
30426
30427     
30428     adjustBodyWidth : function(w){
30429         if(this.header){
30430             this.header.setWidth(w);
30431         }
30432         if(this.footer){
30433             this.footer.setWidth(w);
30434         }
30435         return w;
30436     },
30437
30438     
30439     setActiveTab : function(item){
30440         item = this.getComponent(item);
30441         if(this.fireEvent('beforetabchange', this, item, this.activeTab) === false){
30442             return;
30443         }
30444         if(!this.rendered){
30445             this.activeTab = item;
30446             return;
30447         }
30448         if(this.activeTab != item){
30449             if(this.activeTab){
30450                 var oldEl = this.getTabEl(this.activeTab);
30451                 if(oldEl){
30452                     Ext.fly(oldEl).removeClass('x-tab-strip-active');
30453                 }
30454             }
30455             this.activeTab = item;
30456             if(item){
30457                 var el = this.getTabEl(item);
30458                 Ext.fly(el).addClass('x-tab-strip-active');
30459                 this.stack.add(item);
30460
30461                 this.layout.setActiveItem(item);
30462                 
30463                 this.delegateUpdates();
30464                 if(this.scrolling){
30465                     this.scrollToTab(item, this.animScroll);
30466                 }
30467             }
30468             this.fireEvent('tabchange', this, item);
30469         }
30470     },
30471
30472     
30473     getActiveTab : function(){
30474         return this.activeTab || null;
30475     },
30476
30477     
30478     getItem : function(item){
30479         return this.getComponent(item);
30480     },
30481
30482     
30483     autoScrollTabs : function(){
30484         this.pos = this.tabPosition=='bottom' ? this.footer : this.header;
30485         var count = this.items.length,
30486             ow = this.pos.dom.offsetWidth,
30487             tw = this.pos.dom.clientWidth,
30488             wrap = this.stripWrap,
30489             wd = wrap.dom,
30490             cw = wd.offsetWidth,
30491             pos = this.getScrollPos(),
30492             l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;
30493
30494         if(!this.enableTabScroll || cw < 20){ 
30495             return;
30496         }
30497         if(count == 0 || l <= tw){
30498             
30499             wd.scrollLeft = 0;
30500             wrap.setWidth(tw);
30501             if(this.scrolling){
30502                 this.scrolling = false;
30503                 this.pos.removeClass('x-tab-scrolling');
30504                 this.scrollLeft.hide();
30505                 this.scrollRight.hide();
30506                 
30507                 if(Ext.isAir || Ext.isWebKit){
30508                     wd.style.marginLeft = '';
30509                     wd.style.marginRight = '';
30510                 }
30511             }
30512         }else{
30513             if(!this.scrolling){
30514                 this.pos.addClass('x-tab-scrolling');
30515                 
30516                 if(Ext.isAir || Ext.isWebKit){
30517                     wd.style.marginLeft = '18px';
30518                     wd.style.marginRight = '18px';
30519                 }
30520             }
30521             tw -= wrap.getMargins('lr');
30522             wrap.setWidth(tw > 20 ? tw : 20);
30523             if(!this.scrolling){
30524                 if(!this.scrollLeft){
30525                     this.createScrollers();
30526                 }else{
30527                     this.scrollLeft.show();
30528                     this.scrollRight.show();
30529                 }
30530             }
30531             this.scrolling = true;
30532             if(pos > (l-tw)){ 
30533                 wd.scrollLeft = l-tw;
30534             }else{ 
30535                 this.scrollToTab(this.activeTab, false);
30536             }
30537             this.updateScrollButtons();
30538         }
30539     },
30540
30541     
30542     createScrollers : function(){
30543         this.pos.addClass('x-tab-scrolling-' + this.tabPosition);
30544         var h = this.stripWrap.dom.offsetHeight;
30545
30546         
30547         var sl = this.pos.insertFirst({
30548             cls:'x-tab-scroller-left'
30549         });
30550         sl.setHeight(h);
30551         sl.addClassOnOver('x-tab-scroller-left-over');
30552         this.leftRepeater = new Ext.util.ClickRepeater(sl, {
30553             interval : this.scrollRepeatInterval,
30554             handler: this.onScrollLeft,
30555             scope: this
30556         });
30557         this.scrollLeft = sl;
30558
30559         
30560         var sr = this.pos.insertFirst({
30561             cls:'x-tab-scroller-right'
30562         });
30563         sr.setHeight(h);
30564         sr.addClassOnOver('x-tab-scroller-right-over');
30565         this.rightRepeater = new Ext.util.ClickRepeater(sr, {
30566             interval : this.scrollRepeatInterval,
30567             handler: this.onScrollRight,
30568             scope: this
30569         });
30570         this.scrollRight = sr;
30571     },
30572
30573     
30574     getScrollWidth : function(){
30575         return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();
30576     },
30577
30578     
30579     getScrollPos : function(){
30580         return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;
30581     },
30582
30583     
30584     getScrollArea : function(){
30585         return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;
30586     },
30587
30588     
30589     getScrollAnim : function(){
30590         return {duration:this.scrollDuration, callback: this.updateScrollButtons, scope: this};
30591     },
30592
30593     
30594     getScrollIncrement : function(){
30595         return this.scrollIncrement || (this.resizeTabs ? this.lastTabWidth+2 : 100);
30596     },
30597
30598     
30599
30600     scrollToTab : function(item, animate){
30601         if(!item){
30602             return;
30603         }
30604         var el = this.getTabEl(item),
30605             pos = this.getScrollPos(),
30606             area = this.getScrollArea(),
30607             left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos,
30608             right = left + el.offsetWidth;
30609         if(left < pos){
30610             this.scrollTo(left, animate);
30611         }else if(right > (pos + area)){
30612             this.scrollTo(right - area, animate);
30613         }
30614     },
30615
30616     
30617     scrollTo : function(pos, animate){
30618         this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);
30619         if(!animate){
30620             this.updateScrollButtons();
30621         }
30622     },
30623
30624     onWheel : function(e){
30625         var d = e.getWheelDelta()*this.wheelIncrement*-1;
30626         e.stopEvent();
30627
30628         var pos = this.getScrollPos(),
30629             newpos = pos + d,
30630             sw = this.getScrollWidth()-this.getScrollArea();
30631
30632         var s = Math.max(0, Math.min(sw, newpos));
30633         if(s != pos){
30634             this.scrollTo(s, false);
30635         }
30636     },
30637
30638     
30639     onScrollRight : function(){
30640         var sw = this.getScrollWidth()-this.getScrollArea(),
30641             pos = this.getScrollPos(),
30642             s = Math.min(sw, pos + this.getScrollIncrement());
30643         if(s != pos){
30644             this.scrollTo(s, this.animScroll);
30645         }
30646     },
30647
30648     
30649     onScrollLeft : function(){
30650         var pos = this.getScrollPos(),
30651             s = Math.max(0, pos - this.getScrollIncrement());
30652         if(s != pos){
30653             this.scrollTo(s, this.animScroll);
30654         }
30655     },
30656
30657     
30658     updateScrollButtons : function(){
30659         var pos = this.getScrollPos();
30660         this.scrollLeft[pos === 0 ? 'addClass' : 'removeClass']('x-tab-scroller-left-disabled');
30661         this.scrollRight[pos >= (this.getScrollWidth()-this.getScrollArea()) ? 'addClass' : 'removeClass']('x-tab-scroller-right-disabled');
30662     },
30663
30664     
30665     beforeDestroy : function() {
30666         Ext.destroy(this.leftRepeater, this.rightRepeater);
30667         this.deleteMembers('strip', 'edge', 'scrollLeft', 'scrollRight', 'stripWrap');
30668         this.activeTab = null;
30669         Ext.TabPanel.superclass.beforeDestroy.apply(this);
30670     }
30671
30672     
30673     
30674     
30675     
30676     
30677     
30678     
30679     
30680     
30681     
30682     
30683     
30684 });
30685 Ext.reg('tabpanel', Ext.TabPanel);
30686
30687
30688 Ext.TabPanel.prototype.activate = Ext.TabPanel.prototype.setActiveTab;
30689
30690
30691 Ext.TabPanel.AccessStack = function(){
30692     var items = [];
30693     return {
30694         add : function(item){
30695             items.push(item);
30696             if(items.length > 10){
30697                 items.shift();
30698             }
30699         },
30700
30701         remove : function(item){
30702             var s = [];
30703             for(var i = 0, len = items.length; i < len; i++) {
30704                 if(items[i] != item){
30705                     s.push(items[i]);
30706                 }
30707             }
30708             items = s;
30709         },
30710
30711         next : function(){
30712             return items.pop();
30713         }
30714     };
30715 };
30716
30717 Ext.Button = Ext.extend(Ext.BoxComponent, {
30718     
30719     hidden : false,
30720     
30721     disabled : false,
30722     
30723     pressed : false,
30724
30725     
30726
30727     
30728
30729     
30730     enableToggle : false,
30731     
30732     
30733     
30734     menuAlign : 'tl-bl?',
30735
30736     
30737     
30738     
30739     type : 'button',
30740
30741     
30742     menuClassTarget : 'tr:nth(2)',
30743
30744     
30745     clickEvent : 'click',
30746
30747     
30748     handleMouseEvents : true,
30749
30750     
30751     tooltipType : 'qtip',
30752
30753     
30754     buttonSelector : 'button:first-child',
30755
30756     
30757     scale : 'small',
30758
30759     
30760
30761     
30762     iconAlign : 'left',
30763
30764     
30765     arrowAlign : 'right',
30766
30767     
30768     
30769     
30770     
30771
30772     initComponent : function(){
30773         if(this.menu){
30774             this.menu = Ext.menu.MenuMgr.get(this.menu);
30775             this.menu.ownerCt = this;
30776         }
30777         
30778         Ext.Button.superclass.initComponent.call(this);
30779
30780         this.addEvents(
30781             
30782             'click',
30783             
30784             'toggle',
30785             
30786             'mouseover',
30787             
30788             'mouseout',
30789             
30790             'menushow',
30791             
30792             'menuhide',
30793             
30794             'menutriggerover',
30795             
30796             'menutriggerout'
30797         );
30798         
30799         if (this.menu){
30800             this.menu.ownerCt = undefined;
30801         }
30802         if(Ext.isString(this.toggleGroup)){
30803             this.enableToggle = true;
30804         }
30805     },
30806
30807
30808     getTemplateArgs : function(){
30809         return [this.type, 'x-btn-' + this.scale + ' x-btn-icon-' + this.scale + '-' + this.iconAlign, this.getMenuClass(), this.cls, this.id];
30810     },
30811
30812     
30813     setButtonClass : function(){
30814         if(this.useSetClass){
30815             if(!Ext.isEmpty(this.oldCls)){
30816                 this.el.removeClass([this.oldCls, 'x-btn-pressed']);
30817             }
30818             this.oldCls = (this.iconCls || this.icon) ? (this.text ? 'x-btn-text-icon' : 'x-btn-icon') : 'x-btn-noicon';
30819             this.el.addClass([this.oldCls, this.pressed ? 'x-btn-pressed' : null]);
30820         }
30821     },
30822
30823     
30824     getMenuClass : function(){
30825         return this.menu ? (this.arrowAlign != 'bottom' ? 'x-btn-arrow' : 'x-btn-arrow-bottom') : '';
30826     },
30827
30828     
30829     onRender : function(ct, position){
30830         if(!this.template){
30831             if(!Ext.Button.buttonTemplate){
30832                 
30833                 Ext.Button.buttonTemplate = new Ext.Template(
30834                     '<table id="{4}" cellspacing="0" class="x-btn {3}"><tbody class="{1}">',
30835                     '<tr><td class="x-btn-tl"><i>&#160;</i></td><td class="x-btn-tc"></td><td class="x-btn-tr"><i>&#160;</i></td></tr>',
30836                     '<tr><td class="x-btn-ml"><i>&#160;</i></td><td class="x-btn-mc"><em class="{2}" unselectable="on"><button type="{0}"></button></em></td><td class="x-btn-mr"><i>&#160;</i></td></tr>',
30837                     '<tr><td class="x-btn-bl"><i>&#160;</i></td><td class="x-btn-bc"></td><td class="x-btn-br"><i>&#160;</i></td></tr>',
30838                     '</tbody></table>');
30839                 Ext.Button.buttonTemplate.compile();
30840             }
30841             this.template = Ext.Button.buttonTemplate;
30842         }
30843
30844         var btn, targs = this.getTemplateArgs();
30845
30846         if(position){
30847             btn = this.template.insertBefore(position, targs, true);
30848         }else{
30849             btn = this.template.append(ct, targs, true);
30850         }
30851         
30852         this.btnEl = btn.child(this.buttonSelector);
30853         this.mon(this.btnEl, {
30854             scope: this,
30855             focus: this.onFocus,
30856             blur: this.onBlur
30857         });
30858
30859         this.initButtonEl(btn, this.btnEl);
30860
30861         Ext.ButtonToggleMgr.register(this);
30862     },
30863
30864     
30865     initButtonEl : function(btn, btnEl){
30866         this.el = btn;
30867         this.setIcon(this.icon);
30868         this.setText(this.text);
30869         this.setIconClass(this.iconCls);
30870         if(Ext.isDefined(this.tabIndex)){
30871             btnEl.dom.tabIndex = this.tabIndex;
30872         }
30873         if(this.tooltip){
30874             this.setTooltip(this.tooltip, true);
30875         }
30876
30877         if(this.handleMouseEvents){
30878             this.mon(btn, {
30879                 scope: this,
30880                 mouseover: this.onMouseOver,
30881                 mousedown: this.onMouseDown
30882             });
30883
30884             
30885             
30886         }
30887
30888         if(this.menu){
30889             this.mon(this.menu, {
30890                 scope: this,
30891                 show: this.onMenuShow,
30892                 hide: this.onMenuHide
30893             });
30894         }
30895
30896         if(this.repeat){
30897             var repeater = new Ext.util.ClickRepeater(btn, Ext.isObject(this.repeat) ? this.repeat : {});
30898             this.mon(repeater, 'click', this.onRepeatClick, this);
30899         }else{
30900             this.mon(btn, this.clickEvent, this.onClick, this);
30901         }
30902     },
30903
30904     
30905     afterRender : function(){
30906         Ext.Button.superclass.afterRender.call(this);
30907         this.useSetClass = true;
30908         this.setButtonClass();
30909         this.doc = Ext.getDoc();
30910         this.doAutoWidth();
30911     },
30912
30913     
30914     setIconClass : function(cls){
30915         this.iconCls = cls;
30916         if(this.el){
30917             this.btnEl.dom.className = '';
30918             this.btnEl.addClass(['x-btn-text', cls || '']);
30919             this.setButtonClass();
30920         }
30921         return this;
30922     },
30923
30924     
30925     setTooltip : function(tooltip,  initial){
30926         if(this.rendered){
30927             if(!initial){
30928                 this.clearTip();
30929             }
30930             if(Ext.isObject(tooltip)){
30931                 Ext.QuickTips.register(Ext.apply({
30932                       target: this.btnEl.id
30933                 }, tooltip));
30934                 this.tooltip = tooltip;
30935             }else{
30936                 this.btnEl.dom[this.tooltipType] = tooltip;
30937             }
30938         }else{
30939             this.tooltip = tooltip;
30940         }
30941         return this;
30942     },
30943
30944     
30945     clearTip : function(){
30946         if(Ext.isObject(this.tooltip)){
30947             Ext.QuickTips.unregister(this.btnEl);
30948         }
30949     },
30950
30951     
30952     beforeDestroy : function(){
30953         if(this.rendered){
30954             this.clearTip();
30955         }
30956         if(this.menu && this.destroyMenu !== false) {
30957             Ext.destroy(this.btnEl, this.menu);
30958         }
30959         Ext.destroy(this.repeater);
30960     },
30961
30962     
30963     onDestroy : function(){
30964         if(this.rendered){
30965             this.doc.un('mouseover', this.monitorMouseOver, this);
30966             this.doc.un('mouseup', this.onMouseUp, this);
30967             delete this.doc;
30968             delete this.btnEl;
30969             Ext.ButtonToggleMgr.unregister(this);
30970         }
30971         Ext.Button.superclass.onDestroy.call(this);
30972     },
30973
30974     
30975     doAutoWidth : function(){
30976         if(this.autoWidth !== false && this.el && this.text && this.width === undefined){
30977             this.el.setWidth('auto');
30978             if(Ext.isIE7 && Ext.isStrict){
30979                 var ib = this.btnEl;
30980                 if(ib && ib.getWidth() > 20){
30981                     ib.clip();
30982                     ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
30983                 }
30984             }
30985             if(this.minWidth){
30986                 if(this.el.getWidth() < this.minWidth){
30987                     this.el.setWidth(this.minWidth);
30988                 }
30989             }
30990         }
30991     },
30992
30993     
30994     setHandler : function(handler, scope){
30995         this.handler = handler;
30996         this.scope = scope;
30997         return this;
30998     },
30999
31000     
31001     setText : function(text){
31002         this.text = text;
31003         if(this.el){
31004             this.btnEl.update(text || '&#160;');
31005             this.setButtonClass();
31006         }
31007         this.doAutoWidth();
31008         return this;
31009     },
31010
31011     
31012     setIcon : function(icon){
31013         this.icon = icon;
31014         if(this.el){
31015             this.btnEl.setStyle('background-image', icon ? 'url(' + icon + ')' : '');
31016             this.setButtonClass();
31017         }
31018         return this;
31019     },
31020
31021     
31022     getText : function(){
31023         return this.text;
31024     },
31025
31026     
31027     toggle : function(state, suppressEvent){
31028         state = state === undefined ? !this.pressed : !!state;
31029         if(state != this.pressed){
31030             if(this.rendered){
31031                 this.el[state ? 'addClass' : 'removeClass']('x-btn-pressed');
31032             }
31033             this.pressed = state;
31034             if(!suppressEvent){
31035                 this.fireEvent('toggle', this, state);
31036                 if(this.toggleHandler){
31037                     this.toggleHandler.call(this.scope || this, this, state);
31038                 }
31039             }
31040         }
31041         return this;
31042     },
31043
31044     
31045     onDisable : function(){
31046         this.onDisableChange(true);
31047     },
31048
31049     
31050     onEnable : function(){
31051         this.onDisableChange(false);
31052     },
31053
31054     onDisableChange : function(disabled){
31055         if(this.el){
31056             if(!Ext.isIE6 || !this.text){
31057                 this.el[disabled ? 'addClass' : 'removeClass'](this.disabledClass);
31058             }
31059             this.el.dom.disabled = disabled;
31060         }
31061         this.disabled = disabled;
31062     },
31063
31064     
31065     showMenu : function(){
31066         if(this.rendered && this.menu){
31067             if(this.tooltip){
31068                 Ext.QuickTips.getQuickTip().cancelShow(this.btnEl);
31069             }
31070             if(this.menu.isVisible()){
31071                 this.menu.hide();
31072             }
31073             this.menu.ownerCt = this;
31074             this.menu.show(this.el, this.menuAlign);
31075         }
31076         return this;
31077     },
31078
31079     
31080     hideMenu : function(){
31081         if(this.hasVisibleMenu()){
31082             this.menu.hide();
31083         }
31084         return this;
31085     },
31086
31087     
31088     hasVisibleMenu : function(){
31089         return this.menu && this.menu.ownerCt == this && this.menu.isVisible();
31090     },
31091     
31092     
31093     onRepeatClick : function(repeat, e){
31094         this.onClick(e);
31095     },
31096
31097     
31098     onClick : function(e){
31099         if(e){
31100             e.preventDefault();
31101         }
31102         if(e.button !== 0){
31103             return;
31104         }
31105         if(!this.disabled){
31106             this.doToggle();
31107             if(this.menu && !this.hasVisibleMenu() && !this.ignoreNextClick){
31108                 this.showMenu();
31109             }
31110             this.fireEvent('click', this, e);
31111             if(this.handler){
31112                 
31113                 this.handler.call(this.scope || this, this, e);
31114             }
31115         }
31116     },
31117     
31118     
31119     doToggle: function(){
31120         if (this.enableToggle && (this.allowDepress !== false || !this.pressed)) {
31121             this.toggle();
31122         }
31123     },
31124
31125     
31126     isMenuTriggerOver : function(e, internal){
31127         return this.menu && !internal;
31128     },
31129
31130     
31131     isMenuTriggerOut : function(e, internal){
31132         return this.menu && !internal;
31133     },
31134
31135     
31136     onMouseOver : function(e){
31137         if(!this.disabled){
31138             var internal = e.within(this.el,  true);
31139             if(!internal){
31140                 this.el.addClass('x-btn-over');
31141                 if(!this.monitoringMouseOver){
31142                     this.doc.on('mouseover', this.monitorMouseOver, this);
31143                     this.monitoringMouseOver = true;
31144                 }
31145                 this.fireEvent('mouseover', this, e);
31146             }
31147             if(this.isMenuTriggerOver(e, internal)){
31148                 this.fireEvent('menutriggerover', this, this.menu, e);
31149             }
31150         }
31151     },
31152
31153     
31154     monitorMouseOver : function(e){
31155         if(e.target != this.el.dom && !e.within(this.el)){
31156             if(this.monitoringMouseOver){
31157                 this.doc.un('mouseover', this.monitorMouseOver, this);
31158                 this.monitoringMouseOver = false;
31159             }
31160             this.onMouseOut(e);
31161         }
31162     },
31163
31164     
31165     onMouseOut : function(e){
31166         var internal = e.within(this.el) && e.target != this.el.dom;
31167         this.el.removeClass('x-btn-over');
31168         this.fireEvent('mouseout', this, e);
31169         if(this.isMenuTriggerOut(e, internal)){
31170             this.fireEvent('menutriggerout', this, this.menu, e);
31171         }
31172     },
31173
31174     focus : function() {
31175         this.btnEl.focus();
31176     },
31177
31178     blur : function() {
31179         this.btnEl.blur();
31180     },
31181
31182     
31183     onFocus : function(e){
31184         if(!this.disabled){
31185             this.el.addClass('x-btn-focus');
31186         }
31187     },
31188     
31189     onBlur : function(e){
31190         this.el.removeClass('x-btn-focus');
31191     },
31192
31193     
31194     getClickEl : function(e, isUp){
31195        return this.el;
31196     },
31197
31198     
31199     onMouseDown : function(e){
31200         if(!this.disabled && e.button === 0){
31201             this.getClickEl(e).addClass('x-btn-click');
31202             this.doc.on('mouseup', this.onMouseUp, this);
31203         }
31204     },
31205     
31206     onMouseUp : function(e){
31207         if(e.button === 0){
31208             this.getClickEl(e, true).removeClass('x-btn-click');
31209             this.doc.un('mouseup', this.onMouseUp, this);
31210         }
31211     },
31212     
31213     onMenuShow : function(e){
31214         if(this.menu.ownerCt == this){
31215             this.menu.ownerCt = this;
31216             this.ignoreNextClick = 0;
31217             this.el.addClass('x-btn-menu-active');
31218             this.fireEvent('menushow', this, this.menu);
31219         }
31220     },
31221     
31222     onMenuHide : function(e){
31223         if(this.menu.ownerCt == this){
31224             this.el.removeClass('x-btn-menu-active');
31225             this.ignoreNextClick = this.restoreClick.defer(250, this);
31226             this.fireEvent('menuhide', this, this.menu);
31227             delete this.menu.ownerCt;
31228         }
31229     },
31230
31231     
31232     restoreClick : function(){
31233         this.ignoreNextClick = 0;
31234     }
31235
31236     
31237     
31238     
31239     
31240     
31241     
31242 });
31243 Ext.reg('button', Ext.Button);
31244
31245
31246 Ext.ButtonToggleMgr = function(){
31247    var groups = {};
31248
31249    function toggleGroup(btn, state){
31250        if(state){
31251            var g = groups[btn.toggleGroup];
31252            for(var i = 0, l = g.length; i < l; i++){
31253                if(g[i] != btn){
31254                    g[i].toggle(false);
31255                }
31256            }
31257        }
31258    }
31259
31260    return {
31261        register : function(btn){
31262            if(!btn.toggleGroup){
31263                return;
31264            }
31265            var g = groups[btn.toggleGroup];
31266            if(!g){
31267                g = groups[btn.toggleGroup] = [];
31268            }
31269            g.push(btn);
31270            btn.on('toggle', toggleGroup);
31271        },
31272
31273        unregister : function(btn){
31274            if(!btn.toggleGroup){
31275                return;
31276            }
31277            var g = groups[btn.toggleGroup];
31278            if(g){
31279                g.remove(btn);
31280                btn.un('toggle', toggleGroup);
31281            }
31282        },
31283
31284        
31285        getPressed : function(group){
31286            var g = groups[group];
31287            if(g){
31288                for(var i = 0, len = g.length; i < len; i++){
31289                    if(g[i].pressed === true){
31290                        return g[i];
31291                    }
31292                }
31293            }
31294            return null;
31295        }
31296    };
31297 }();
31298
31299 Ext.SplitButton = Ext.extend(Ext.Button, {
31300         
31301     arrowSelector : 'em',
31302     split: true,
31303
31304     
31305     initComponent : function(){
31306         Ext.SplitButton.superclass.initComponent.call(this);
31307         
31308         this.addEvents("arrowclick");
31309     },
31310
31311     
31312     onRender : function(){
31313         Ext.SplitButton.superclass.onRender.apply(this, arguments);
31314         if(this.arrowTooltip){
31315             this.el.child(this.arrowSelector).dom[this.tooltipType] = this.arrowTooltip;
31316         }
31317     },
31318
31319     
31320     setArrowHandler : function(handler, scope){
31321         this.arrowHandler = handler;
31322         this.scope = scope;
31323     },
31324
31325     getMenuClass : function(){
31326         return 'x-btn-split' + (this.arrowAlign == 'bottom' ? '-bottom' : '');
31327     },
31328
31329     isClickOnArrow : function(e){
31330         if (this.arrowAlign != 'bottom') {
31331             var visBtn = this.el.child('em.x-btn-split');
31332             var right = visBtn.getRegion().right - visBtn.getPadding('r');
31333             return e.getPageX() > right;
31334         } else {
31335             return e.getPageY() > this.btnEl.getRegion().bottom;
31336         }
31337     },
31338
31339     
31340     onClick : function(e, t){
31341         e.preventDefault();
31342         if(!this.disabled){
31343             if(this.isClickOnArrow(e)){
31344                 if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){
31345                     this.showMenu();
31346                 }
31347                 this.fireEvent("arrowclick", this, e);
31348                 if(this.arrowHandler){
31349                     this.arrowHandler.call(this.scope || this, this, e);
31350                 }
31351             }else{
31352                 this.doToggle();
31353                 this.fireEvent("click", this, e);
31354                 if(this.handler){
31355                     this.handler.call(this.scope || this, this, e);
31356                 }
31357             }
31358         }
31359     },
31360
31361     
31362     isMenuTriggerOver : function(e){
31363         return this.menu && e.target.tagName == this.arrowSelector;
31364     },
31365
31366     
31367     isMenuTriggerOut : function(e, internal){
31368         return this.menu && e.target.tagName != this.arrowSelector;
31369     }
31370 });
31371
31372 Ext.reg('splitbutton', Ext.SplitButton);
31373 Ext.CycleButton = Ext.extend(Ext.SplitButton, {
31374     
31375     
31376     
31377     
31378     
31379     
31380
31381     
31382     getItemText : function(item){
31383         if(item && this.showText === true){
31384             var text = '';
31385             if(this.prependText){
31386                 text += this.prependText;
31387             }
31388             text += item.text;
31389             return text;
31390         }
31391         return undefined;
31392     },
31393
31394     
31395     setActiveItem : function(item, suppressEvent){
31396         if(!Ext.isObject(item)){
31397             item = this.menu.getComponent(item);
31398         }
31399         if(item){
31400             if(!this.rendered){
31401                 this.text = this.getItemText(item);
31402                 this.iconCls = item.iconCls;
31403             }else{
31404                 var t = this.getItemText(item);
31405                 if(t){
31406                     this.setText(t);
31407                 }
31408                 this.setIconClass(item.iconCls);
31409             }
31410             this.activeItem = item;
31411             if(!item.checked){
31412                 item.setChecked(true, false);
31413             }
31414             if(this.forceIcon){
31415                 this.setIconClass(this.forceIcon);
31416             }
31417             if(!suppressEvent){
31418                 this.fireEvent('change', this, item);
31419             }
31420         }
31421     },
31422
31423     
31424     getActiveItem : function(){
31425         return this.activeItem;
31426     },
31427
31428     
31429     initComponent : function(){
31430         this.addEvents(
31431             
31432             "change"
31433         );
31434
31435         if(this.changeHandler){
31436             this.on('change', this.changeHandler, this.scope||this);
31437             delete this.changeHandler;
31438         }
31439
31440         this.itemCount = this.items.length;
31441
31442         this.menu = {cls:'x-cycle-menu', items:[]};
31443         var checked = 0;
31444         Ext.each(this.items, function(item, i){
31445             Ext.apply(item, {
31446                 group: item.group || this.id,
31447                 itemIndex: i,
31448                 checkHandler: this.checkHandler,
31449                 scope: this,
31450                 checked: item.checked || false
31451             });
31452             this.menu.items.push(item);
31453             if(item.checked){
31454                 checked = i;
31455             }
31456         }, this);
31457         Ext.CycleButton.superclass.initComponent.call(this);
31458         this.on('click', this.toggleSelected, this);
31459         this.setActiveItem(checked, true);
31460     },
31461
31462     
31463     checkHandler : function(item, pressed){
31464         if(pressed){
31465             this.setActiveItem(item);
31466         }
31467     },
31468
31469     
31470     toggleSelected : function(){
31471         var m = this.menu;
31472         m.render();
31473         
31474         if(!m.hasLayout){
31475             m.doLayout();
31476         }
31477         
31478         var nextIdx, checkItem;
31479         for (var i = 1; i < this.itemCount; i++) {
31480             nextIdx = (this.activeItem.itemIndex + i) % this.itemCount;
31481             
31482             checkItem = m.items.itemAt(nextIdx);
31483             
31484             if (!checkItem.disabled) {
31485                 checkItem.setChecked(true);
31486                 break;
31487             }
31488         }
31489     }
31490 });
31491 Ext.reg('cycle', Ext.CycleButton);
31492 Ext.Toolbar = function(config){
31493     if(Ext.isArray(config)){
31494         config = {items: config, layout: 'toolbar'};
31495     } else {
31496         config = Ext.apply({
31497             layout: 'toolbar'
31498         }, config);
31499         if(config.buttons) {
31500             config.items = config.buttons;
31501         }
31502     }
31503     Ext.Toolbar.superclass.constructor.call(this, config);
31504 };
31505
31506 (function(){
31507
31508 var T = Ext.Toolbar;
31509
31510 Ext.extend(T, Ext.Container, {
31511
31512     defaultType: 'button',
31513
31514     
31515
31516     enableOverflow : false,
31517
31518     
31519     
31520
31521     trackMenus : true,
31522     internalDefaults: {removeMode: 'container', hideParent: true},
31523     toolbarCls: 'x-toolbar',
31524
31525     initComponent : function(){
31526         T.superclass.initComponent.call(this);
31527
31528         
31529         this.addEvents('overflowchange');
31530     },
31531
31532     
31533     onRender : function(ct, position){
31534         if(!this.el){
31535             if(!this.autoCreate){
31536                 this.autoCreate = {
31537                     cls: this.toolbarCls + ' x-small-editor'
31538                 };
31539             }
31540             this.el = ct.createChild(Ext.apply({ id: this.id },this.autoCreate), position);
31541             Ext.Toolbar.superclass.onRender.apply(this, arguments);
31542         }
31543     },
31544
31545     
31546
31547     
31548     lookupComponent : function(c){
31549         if(Ext.isString(c)){
31550             if(c == '-'){
31551                 c = new T.Separator();
31552             }else if(c == ' '){
31553                 c = new T.Spacer();
31554             }else if(c == '->'){
31555                 c = new T.Fill();
31556             }else{
31557                 c = new T.TextItem(c);
31558             }
31559             this.applyDefaults(c);
31560         }else{
31561             if(c.isFormField || c.render){ 
31562                 c = this.createComponent(c);
31563             }else if(c.tag){ 
31564                 c = new T.Item({autoEl: c});
31565             }else if(c.tagName){ 
31566                 c = new T.Item({el:c});
31567             }else if(Ext.isObject(c)){ 
31568                 c = c.xtype ? this.createComponent(c) : this.constructButton(c);
31569             }
31570         }
31571         return c;
31572     },
31573
31574     
31575     applyDefaults : function(c){
31576         if(!Ext.isString(c)){
31577             c = Ext.Toolbar.superclass.applyDefaults.call(this, c);
31578             var d = this.internalDefaults;
31579             if(c.events){
31580                 Ext.applyIf(c.initialConfig, d);
31581                 Ext.apply(c, d);
31582             }else{
31583                 Ext.applyIf(c, d);
31584             }
31585         }
31586         return c;
31587     },
31588
31589     
31590     addSeparator : function(){
31591         return this.add(new T.Separator());
31592     },
31593
31594     
31595     addSpacer : function(){
31596         return this.add(new T.Spacer());
31597     },
31598
31599     
31600     addFill : function(){
31601         this.add(new T.Fill());
31602     },
31603
31604     
31605     addElement : function(el){
31606         return this.addItem(new T.Item({el:el}));
31607     },
31608
31609     
31610     addItem : function(item){
31611         return this.add.apply(this, arguments);
31612     },
31613
31614     
31615     addButton : function(config){
31616         if(Ext.isArray(config)){
31617             var buttons = [];
31618             for(var i = 0, len = config.length; i < len; i++) {
31619                 buttons.push(this.addButton(config[i]));
31620             }
31621             return buttons;
31622         }
31623         return this.add(this.constructButton(config));
31624     },
31625
31626     
31627     addText : function(text){
31628         return this.addItem(new T.TextItem(text));
31629     },
31630
31631     
31632     addDom : function(config){
31633         return this.add(new T.Item({autoEl: config}));
31634     },
31635
31636     
31637     addField : function(field){
31638         return this.add(field);
31639     },
31640
31641     
31642     insertButton : function(index, item){
31643         if(Ext.isArray(item)){
31644             var buttons = [];
31645             for(var i = 0, len = item.length; i < len; i++) {
31646                buttons.push(this.insertButton(index + i, item[i]));
31647             }
31648             return buttons;
31649         }
31650         return Ext.Toolbar.superclass.insert.call(this, index, item);
31651     },
31652
31653     
31654     trackMenu : function(item, remove){
31655         if(this.trackMenus && item.menu){
31656             var method = remove ? 'mun' : 'mon';
31657             this[method](item, 'menutriggerover', this.onButtonTriggerOver, this);
31658             this[method](item, 'menushow', this.onButtonMenuShow, this);
31659             this[method](item, 'menuhide', this.onButtonMenuHide, this);
31660         }
31661     },
31662
31663     
31664     constructButton : function(item){
31665         var b = item.events ? item : this.createComponent(item, item.split ? 'splitbutton' : this.defaultType);
31666         return b;
31667     },
31668
31669     
31670     onAdd : function(c){
31671         Ext.Toolbar.superclass.onAdd.call(this);
31672         this.trackMenu(c);
31673         if(this.disabled){
31674             c.disable();
31675         }
31676     },
31677
31678     
31679     onRemove : function(c){
31680         Ext.Toolbar.superclass.onRemove.call(this);
31681         if (c == this.activeMenuBtn) {
31682             delete this.activeMenuBtn;
31683         }
31684         this.trackMenu(c, true);
31685     },
31686
31687     
31688     onDisable : function(){
31689         this.items.each(function(item){
31690              if(item.disable){
31691                  item.disable();
31692              }
31693         });
31694     },
31695
31696     
31697     onEnable : function(){
31698         this.items.each(function(item){
31699              if(item.enable){
31700                  item.enable();
31701              }
31702         });
31703     },
31704
31705     
31706     onButtonTriggerOver : function(btn){
31707         if(this.activeMenuBtn && this.activeMenuBtn != btn){
31708             this.activeMenuBtn.hideMenu();
31709             btn.showMenu();
31710             this.activeMenuBtn = btn;
31711         }
31712     },
31713
31714     
31715     onButtonMenuShow : function(btn){
31716         this.activeMenuBtn = btn;
31717     },
31718
31719     
31720     onButtonMenuHide : function(btn){
31721         delete this.activeMenuBtn;
31722     }
31723 });
31724 Ext.reg('toolbar', Ext.Toolbar);
31725
31726
31727 T.Item = Ext.extend(Ext.BoxComponent, {
31728     hideParent: true, 
31729     enable:Ext.emptyFn,
31730     disable:Ext.emptyFn,
31731     focus:Ext.emptyFn
31732     
31733 });
31734 Ext.reg('tbitem', T.Item);
31735
31736
31737 T.Separator = Ext.extend(T.Item, {
31738     onRender : function(ct, position){
31739         this.el = ct.createChild({tag:'span', cls:'xtb-sep'}, position);
31740     }
31741 });
31742 Ext.reg('tbseparator', T.Separator);
31743
31744
31745 T.Spacer = Ext.extend(T.Item, {
31746     
31747
31748     onRender : function(ct, position){
31749         this.el = ct.createChild({tag:'div', cls:'xtb-spacer', style: this.width?'width:'+this.width+'px':''}, position);
31750     }
31751 });
31752 Ext.reg('tbspacer', T.Spacer);
31753
31754
31755 T.Fill = Ext.extend(T.Item, {
31756     
31757     render : Ext.emptyFn,
31758     isFill : true
31759 });
31760 Ext.reg('tbfill', T.Fill);
31761
31762
31763 T.TextItem = Ext.extend(T.Item, {
31764     
31765
31766     constructor: function(config){
31767         T.TextItem.superclass.constructor.call(this, Ext.isString(config) ? {text: config} : config);
31768     },
31769
31770     
31771     onRender : function(ct, position) {
31772         this.autoEl = {cls: 'xtb-text', html: this.text || ''};
31773         T.TextItem.superclass.onRender.call(this, ct, position);
31774     },
31775
31776     
31777     setText : function(t) {
31778         if(this.rendered){
31779             this.el.update(t);
31780         }else{
31781             this.text = t;
31782         }
31783     }
31784 });
31785 Ext.reg('tbtext', T.TextItem);
31786
31787
31788 T.Button = Ext.extend(Ext.Button, {});
31789 T.SplitButton = Ext.extend(Ext.SplitButton, {});
31790 Ext.reg('tbbutton', T.Button);
31791 Ext.reg('tbsplit', T.SplitButton);
31792
31793 })();
31794
31795 Ext.ButtonGroup = Ext.extend(Ext.Panel, {
31796     
31797     
31798     baseCls: 'x-btn-group',
31799     
31800     layout:'table',
31801     defaultType: 'button',
31802     
31803     frame: true,
31804     internalDefaults: {removeMode: 'container', hideParent: true},
31805
31806     initComponent : function(){
31807         this.layoutConfig = this.layoutConfig || {};
31808         Ext.applyIf(this.layoutConfig, {
31809             columns : this.columns
31810         });
31811         if(!this.title){
31812             this.addClass('x-btn-group-notitle');
31813         }
31814         this.on('afterlayout', this.onAfterLayout, this);
31815         Ext.ButtonGroup.superclass.initComponent.call(this);
31816     },
31817
31818     applyDefaults : function(c){
31819         c = Ext.ButtonGroup.superclass.applyDefaults.call(this, c);
31820         var d = this.internalDefaults;
31821         if(c.events){
31822             Ext.applyIf(c.initialConfig, d);
31823             Ext.apply(c, d);
31824         }else{
31825             Ext.applyIf(c, d);
31826         }
31827         return c;
31828     },
31829
31830     onAfterLayout : function(){
31831         var bodyWidth = this.body.getFrameWidth('lr') + this.body.dom.firstChild.offsetWidth;
31832         this.body.setWidth(bodyWidth);
31833         this.el.setWidth(bodyWidth + this.getFrameWidth());
31834     }
31835     
31836 });
31837
31838 Ext.reg('buttongroup', Ext.ButtonGroup);
31839
31840 (function() {
31841
31842 var T = Ext.Toolbar;
31843
31844 Ext.PagingToolbar = Ext.extend(Ext.Toolbar, {
31845     
31846     
31847     
31848     pageSize : 20,
31849     
31850     
31851     displayMsg : 'Displaying {0} - {1} of {2}',
31852     
31853     emptyMsg : 'No data to display',
31854     
31855     beforePageText : 'Page',
31856     
31857     afterPageText : 'of {0}',
31858     
31859     firstText : 'First Page',
31860     
31861     prevText : 'Previous Page',
31862     
31863     nextText : 'Next Page',
31864     
31865     lastText : 'Last Page',
31866     
31867     refreshText : 'Refresh',
31868
31869     
31870
31871     
31872
31873     
31874
31875     initComponent : function(){
31876         var pagingItems = [this.first = new T.Button({
31877             tooltip: this.firstText,
31878             overflowText: this.firstText,
31879             iconCls: 'x-tbar-page-first',
31880             disabled: true,
31881             handler: this.moveFirst,
31882             scope: this
31883         }), this.prev = new T.Button({
31884             tooltip: this.prevText,
31885             overflowText: this.prevText,
31886             iconCls: 'x-tbar-page-prev',
31887             disabled: true,
31888             handler: this.movePrevious,
31889             scope: this
31890         }), '-', this.beforePageText,
31891         this.inputItem = new Ext.form.NumberField({
31892             cls: 'x-tbar-page-number',
31893             allowDecimals: false,
31894             allowNegative: false,
31895             enableKeyEvents: true,
31896             selectOnFocus: true,
31897             submitValue: false,
31898             listeners: {
31899                 scope: this,
31900                 keydown: this.onPagingKeyDown,
31901                 blur: this.onPagingBlur
31902             }
31903         }), this.afterTextItem = new T.TextItem({
31904             text: String.format(this.afterPageText, 1)
31905         }), '-', this.next = new T.Button({
31906             tooltip: this.nextText,
31907             overflowText: this.nextText,
31908             iconCls: 'x-tbar-page-next',
31909             disabled: true,
31910             handler: this.moveNext,
31911             scope: this
31912         }), this.last = new T.Button({
31913             tooltip: this.lastText,
31914             overflowText: this.lastText,
31915             iconCls: 'x-tbar-page-last',
31916             disabled: true,
31917             handler: this.moveLast,
31918             scope: this
31919         }), '-', this.refresh = new T.Button({
31920             tooltip: this.refreshText,
31921             overflowText: this.refreshText,
31922             iconCls: 'x-tbar-loading',
31923             handler: this.doRefresh,
31924             scope: this
31925         })];
31926
31927
31928         var userItems = this.items || this.buttons || [];
31929         if (this.prependButtons) {
31930             this.items = userItems.concat(pagingItems);
31931         }else{
31932             this.items = pagingItems.concat(userItems);
31933         }
31934         delete this.buttons;
31935         if(this.displayInfo){
31936             this.items.push('->');
31937             this.items.push(this.displayItem = new T.TextItem({}));
31938         }
31939         Ext.PagingToolbar.superclass.initComponent.call(this);
31940         this.addEvents(
31941             
31942             'change',
31943             
31944             'beforechange'
31945         );
31946         this.on('afterlayout', this.onFirstLayout, this, {single: true});
31947         this.cursor = 0;
31948         this.bindStore(this.store, true);
31949     },
31950
31951     
31952     onFirstLayout : function(){
31953         if(this.dsLoaded){
31954             this.onLoad.apply(this, this.dsLoaded);
31955         }
31956     },
31957
31958     
31959     updateInfo : function(){
31960         if(this.displayItem){
31961             var count = this.store.getCount();
31962             var msg = count == 0 ?
31963                 this.emptyMsg :
31964                 String.format(
31965                     this.displayMsg,
31966                     this.cursor+1, this.cursor+count, this.store.getTotalCount()
31967                 );
31968             this.displayItem.setText(msg);
31969         }
31970     },
31971
31972     
31973     onLoad : function(store, r, o){
31974         if(!this.rendered){
31975             this.dsLoaded = [store, r, o];
31976             return;
31977         }
31978         var p = this.getParams();
31979         this.cursor = (o.params && o.params[p.start]) ? o.params[p.start] : 0;
31980         var d = this.getPageData(), ap = d.activePage, ps = d.pages;
31981
31982         this.afterTextItem.setText(String.format(this.afterPageText, d.pages));
31983         this.inputItem.setValue(ap);
31984         this.first.setDisabled(ap == 1);
31985         this.prev.setDisabled(ap == 1);
31986         this.next.setDisabled(ap == ps);
31987         this.last.setDisabled(ap == ps);
31988         this.refresh.enable();
31989         this.updateInfo();
31990         this.fireEvent('change', this, d);
31991     },
31992
31993     
31994     getPageData : function(){
31995         var total = this.store.getTotalCount();
31996         return {
31997             total : total,
31998             activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
31999             pages :  total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
32000         };
32001     },
32002
32003     
32004     changePage : function(page){
32005         this.doLoad(((page-1) * this.pageSize).constrain(0, this.store.getTotalCount()));
32006     },
32007
32008     
32009     onLoadError : function(){
32010         if(!this.rendered){
32011             return;
32012         }
32013         this.refresh.enable();
32014     },
32015
32016     
32017     readPage : function(d){
32018         var v = this.inputItem.getValue(), pageNum;
32019         if (!v || isNaN(pageNum = parseInt(v, 10))) {
32020             this.inputItem.setValue(d.activePage);
32021             return false;
32022         }
32023         return pageNum;
32024     },
32025
32026     onPagingFocus : function(){
32027         this.inputItem.select();
32028     },
32029
32030     
32031     onPagingBlur : function(e){
32032         this.inputItem.setValue(this.getPageData().activePage);
32033     },
32034
32035     
32036     onPagingKeyDown : function(field, e){
32037         var k = e.getKey(), d = this.getPageData(), pageNum;
32038         if (k == e.RETURN) {
32039             e.stopEvent();
32040             pageNum = this.readPage(d);
32041             if(pageNum !== false){
32042                 pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
32043                 this.doLoad(pageNum * this.pageSize);
32044             }
32045         }else if (k == e.HOME || k == e.END){
32046             e.stopEvent();
32047             pageNum = k == e.HOME ? 1 : d.pages;
32048             field.setValue(pageNum);
32049         }else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN){
32050             e.stopEvent();
32051             if((pageNum = this.readPage(d))){
32052                 var increment = e.shiftKey ? 10 : 1;
32053                 if(k == e.DOWN || k == e.PAGEDOWN){
32054                     increment *= -1;
32055                 }
32056                 pageNum += increment;
32057                 if(pageNum >= 1 & pageNum <= d.pages){
32058                     field.setValue(pageNum);
32059                 }
32060             }
32061         }
32062     },
32063
32064     
32065     getParams : function(){
32066         
32067         return this.paramNames || this.store.paramNames;
32068     },
32069
32070     
32071     beforeLoad : function(){
32072         if(this.rendered && this.refresh){
32073             this.refresh.disable();
32074         }
32075     },
32076
32077     
32078     doLoad : function(start){
32079         var o = {}, pn = this.getParams();
32080         o[pn.start] = start;
32081         o[pn.limit] = this.pageSize;
32082         if(this.fireEvent('beforechange', this, o) !== false){
32083             this.store.load({params:o});
32084         }
32085     },
32086
32087     
32088     moveFirst : function(){
32089         this.doLoad(0);
32090     },
32091
32092     
32093     movePrevious : function(){
32094         this.doLoad(Math.max(0, this.cursor-this.pageSize));
32095     },
32096
32097     
32098     moveNext : function(){
32099         this.doLoad(this.cursor+this.pageSize);
32100     },
32101
32102     
32103     moveLast : function(){
32104         var total = this.store.getTotalCount(),
32105             extra = total % this.pageSize;
32106
32107         this.doLoad(extra ? (total - extra) : total - this.pageSize);
32108     },
32109
32110     
32111     doRefresh : function(){
32112         this.doLoad(this.cursor);
32113     },
32114
32115     
32116     bindStore : function(store, initial){
32117         var doLoad;
32118         if(!initial && this.store){
32119             if(store !== this.store && this.store.autoDestroy){
32120                 this.store.destroy();
32121             }else{
32122                 this.store.un('beforeload', this.beforeLoad, this);
32123                 this.store.un('load', this.onLoad, this);
32124                 this.store.un('exception', this.onLoadError, this);
32125             }
32126             if(!store){
32127                 this.store = null;
32128             }
32129         }
32130         if(store){
32131             store = Ext.StoreMgr.lookup(store);
32132             store.on({
32133                 scope: this,
32134                 beforeload: this.beforeLoad,
32135                 load: this.onLoad,
32136                 exception: this.onLoadError
32137             });
32138             doLoad = true;
32139         }
32140         this.store = store;
32141         if(doLoad){
32142             this.onLoad(store, null, {});
32143         }
32144     },
32145
32146     
32147     unbind : function(store){
32148         this.bindStore(null);
32149     },
32150
32151     
32152     bind : function(store){
32153         this.bindStore(store);
32154     },
32155
32156     
32157     onDestroy : function(){
32158         this.bindStore(null);
32159         Ext.PagingToolbar.superclass.onDestroy.call(this);
32160     }
32161 });
32162
32163 })();
32164 Ext.reg('paging', Ext.PagingToolbar);
32165 Ext.History = (function () {
32166     var iframe, hiddenField;
32167     var ready = false;
32168     var currentToken;
32169
32170     function getHash() {
32171         var href = location.href, i = href.indexOf("#");
32172         return i >= 0 ? href.substr(i + 1) : null;
32173     }
32174
32175     function doSave() {
32176         hiddenField.value = currentToken;
32177     }
32178
32179     function handleStateChange(token) {
32180         currentToken = token;
32181         Ext.History.fireEvent('change', token);
32182     }
32183
32184     function updateIFrame (token) {
32185         var html = ['<html><body><div id="state">',Ext.util.Format.htmlEncode(token),'</div></body></html>'].join('');
32186         try {
32187             var doc = iframe.contentWindow.document;
32188             doc.open();
32189             doc.write(html);
32190             doc.close();
32191             return true;
32192         } catch (e) {
32193             return false;
32194         }
32195     }
32196
32197     function checkIFrame() {
32198         if (!iframe.contentWindow || !iframe.contentWindow.document) {
32199             setTimeout(checkIFrame, 10);
32200             return;
32201         }
32202
32203         var doc = iframe.contentWindow.document;
32204         var elem = doc.getElementById("state");
32205         var token = elem ? elem.innerText : null;
32206
32207         var hash = getHash();
32208
32209         setInterval(function () {
32210
32211             doc = iframe.contentWindow.document;
32212             elem = doc.getElementById("state");
32213
32214             var newtoken = elem ? elem.innerText : null;
32215
32216             var newHash = getHash();
32217
32218             if (newtoken !== token) {
32219                 token = newtoken;
32220                 handleStateChange(token);
32221                 top.location.hash = token;
32222                 hash = token;
32223                 doSave();
32224             } else if (newHash !== hash) {
32225                 hash = newHash;
32226                 updateIFrame(newHash);
32227             }
32228
32229         }, 50);
32230
32231         ready = true;
32232
32233         Ext.History.fireEvent('ready', Ext.History);
32234     }
32235
32236     function startUp() {
32237         currentToken = hiddenField.value ? hiddenField.value : getHash();
32238
32239         if (Ext.isIE) {
32240             checkIFrame();
32241         } else {
32242             var hash = getHash();
32243             setInterval(function () {
32244                 var newHash = getHash();
32245                 if (newHash !== hash) {
32246                     hash = newHash;
32247                     handleStateChange(hash);
32248                     doSave();
32249                 }
32250             }, 50);
32251             ready = true;
32252             Ext.History.fireEvent('ready', Ext.History);
32253         }
32254     }
32255
32256     return {
32257         
32258         fieldId: 'x-history-field',
32259         
32260         iframeId: 'x-history-frame',
32261
32262         events:{},
32263
32264         
32265         init: function (onReady, scope) {
32266             if(ready) {
32267                 Ext.callback(onReady, scope, [this]);
32268                 return;
32269             }
32270             if(!Ext.isReady){
32271                 Ext.onReady(function(){
32272                     Ext.History.init(onReady, scope);
32273                 });
32274                 return;
32275             }
32276             hiddenField = Ext.getDom(Ext.History.fieldId);
32277             if (Ext.isIE) {
32278                 iframe = Ext.getDom(Ext.History.iframeId);
32279             }
32280             this.addEvents(
32281                 
32282                 'ready',
32283                 
32284                 'change'
32285             );
32286             if(onReady){
32287                 this.on('ready', onReady, scope, {single:true});
32288             }
32289             startUp();
32290         },
32291
32292         
32293         add: function (token, preventDup) {
32294             if(preventDup !== false){
32295                 if(this.getToken() == token){
32296                     return true;
32297                 }
32298             }
32299             if (Ext.isIE) {
32300                 return updateIFrame(token);
32301             } else {
32302                 top.location.hash = token;
32303                 return true;
32304             }
32305         },
32306
32307         
32308         back: function(){
32309             history.go(-1);
32310         },
32311
32312         
32313         forward: function(){
32314             history.go(1);
32315         },
32316
32317         
32318         getToken: function() {
32319             return ready ? currentToken : getHash();
32320         }
32321     };
32322 })();
32323 Ext.apply(Ext.History, new Ext.util.Observable());
32324 Ext.Tip = Ext.extend(Ext.Panel, {
32325     
32326     
32327     
32328     minWidth : 40,
32329     
32330     maxWidth : 300,
32331     
32332     shadow : "sides",
32333     
32334     defaultAlign : "tl-bl?",
32335     autoRender: true,
32336     quickShowInterval : 250,
32337
32338     
32339     frame:true,
32340     hidden:true,
32341     baseCls: 'x-tip',
32342     floating:{shadow:true,shim:true,useDisplay:true,constrain:false},
32343     autoHeight:true,
32344
32345     closeAction: 'hide',
32346
32347     
32348     initComponent : function(){
32349         Ext.Tip.superclass.initComponent.call(this);
32350         if(this.closable && !this.title){
32351             this.elements += ',header';
32352         }
32353     },
32354
32355     
32356     afterRender : function(){
32357         Ext.Tip.superclass.afterRender.call(this);
32358         if(this.closable){
32359             this.addTool({
32360                 id: 'close',
32361                 handler: this[this.closeAction],
32362                 scope: this
32363             });
32364         }
32365     },
32366
32367     
32368     showAt : function(xy){
32369         Ext.Tip.superclass.show.call(this);
32370         if(this.measureWidth !== false && (!this.initialConfig || typeof this.initialConfig.width != 'number')){
32371             this.doAutoWidth();
32372         }
32373         if(this.constrainPosition){
32374             xy = this.el.adjustForConstraints(xy);
32375         }
32376         this.setPagePosition(xy[0], xy[1]);
32377     },
32378
32379     
32380     doAutoWidth : function(adjust){
32381         adjust = adjust || 0;
32382         var bw = this.body.getTextWidth();
32383         if(this.title){
32384             bw = Math.max(bw, this.header.child('span').getTextWidth(this.title));
32385         }
32386         bw += this.getFrameWidth() + (this.closable ? 20 : 0) + this.body.getPadding("lr") + adjust;
32387         this.setWidth(bw.constrain(this.minWidth, this.maxWidth));
32388         
32389         
32390         if(Ext.isIE7 && !this.repainted){
32391             this.el.repaint();
32392             this.repainted = true;
32393         }
32394     },
32395
32396     
32397     showBy : function(el, pos){
32398         if(!this.rendered){
32399             this.render(Ext.getBody());
32400         }
32401         this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
32402     },
32403
32404     initDraggable : function(){
32405         this.dd = new Ext.Tip.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);
32406         this.header.addClass('x-tip-draggable');
32407     }
32408 });
32409
32410 Ext.reg('tip', Ext.Tip);
32411
32412
32413 Ext.Tip.DD = function(tip, config){
32414     Ext.apply(this, config);
32415     this.tip = tip;
32416     Ext.Tip.DD.superclass.constructor.call(this, tip.el.id, 'WindowDD-'+tip.id);
32417     this.setHandleElId(tip.header.id);
32418     this.scroll = false;
32419 };
32420
32421 Ext.extend(Ext.Tip.DD, Ext.dd.DD, {
32422     moveOnly:true,
32423     scroll:false,
32424     headerOffsets:[100, 25],
32425     startDrag : function(){
32426         this.tip.el.disableShadow();
32427     },
32428     endDrag : function(e){
32429         this.tip.el.enableShadow(true);
32430     }
32431 });
32432 Ext.ToolTip = Ext.extend(Ext.Tip, {
32433     
32434     
32435     
32436     
32437     showDelay : 500,
32438     
32439     hideDelay : 200,
32440     
32441     dismissDelay : 5000,
32442     
32443     
32444     trackMouse : false,
32445     
32446     anchorToTarget : true,
32447     
32448     anchorOffset : 0,
32449     
32450
32451     
32452     targetCounter : 0,
32453
32454     constrainPosition : false,
32455
32456     
32457     initComponent : function(){
32458         Ext.ToolTip.superclass.initComponent.call(this);
32459         this.lastActive = new Date();
32460         this.initTarget(this.target);
32461         this.origAnchor = this.anchor;
32462     },
32463
32464     
32465     onRender : function(ct, position){
32466         Ext.ToolTip.superclass.onRender.call(this, ct, position);
32467         this.anchorCls = 'x-tip-anchor-' + this.getAnchorPosition();
32468         this.anchorEl = this.el.createChild({
32469             cls: 'x-tip-anchor ' + this.anchorCls
32470         });
32471     },
32472
32473     
32474     afterRender : function(){
32475         Ext.ToolTip.superclass.afterRender.call(this);
32476         this.anchorEl.setStyle('z-index', this.el.getZIndex() + 1).setVisibilityMode(Ext.Element.DISPLAY);
32477     },
32478
32479     
32480     initTarget : function(target){
32481         var t;
32482         if((t = Ext.get(target))){
32483             if(this.target){
32484                 var tg = Ext.get(this.target);
32485                 this.mun(tg, 'mouseover', this.onTargetOver, this);
32486                 this.mun(tg, 'mouseout', this.onTargetOut, this);
32487                 this.mun(tg, 'mousemove', this.onMouseMove, this);
32488             }
32489             this.mon(t, {
32490                 mouseover: this.onTargetOver,
32491                 mouseout: this.onTargetOut,
32492                 mousemove: this.onMouseMove,
32493                 scope: this
32494             });
32495             this.target = t;
32496         }
32497         if(this.anchor){
32498             this.anchorTarget = this.target;
32499         }
32500     },
32501
32502     
32503     onMouseMove : function(e){
32504         var t = this.delegate ? e.getTarget(this.delegate) : this.triggerElement = true;
32505         if (t) {
32506             this.targetXY = e.getXY();
32507             if (t === this.triggerElement) {
32508                 if(!this.hidden && this.trackMouse){
32509                     this.setPagePosition(this.getTargetXY());
32510                 }
32511             } else {
32512                 this.hide();
32513                 this.lastActive = new Date(0);
32514                 this.onTargetOver(e);
32515             }
32516         } else if (!this.closable && this.isVisible()) {
32517             this.hide();
32518         }
32519     },
32520
32521     
32522     getTargetXY : function(){
32523         if(this.delegate){
32524             this.anchorTarget = this.triggerElement;
32525         }
32526         if(this.anchor){
32527             this.targetCounter++;
32528             var offsets = this.getOffsets(),
32529                 xy = (this.anchorToTarget && !this.trackMouse) ? this.el.getAlignToXY(this.anchorTarget, this.getAnchorAlign()) : this.targetXY,
32530                 dw = Ext.lib.Dom.getViewWidth() - 5,
32531                 dh = Ext.lib.Dom.getViewHeight() - 5,
32532                 de = document.documentElement,
32533                 bd = document.body,
32534                 scrollX = (de.scrollLeft || bd.scrollLeft || 0) + 5,
32535                 scrollY = (de.scrollTop || bd.scrollTop || 0) + 5,
32536                 axy = [xy[0] + offsets[0], xy[1] + offsets[1]],
32537                 sz = this.getSize();
32538                 
32539             this.anchorEl.removeClass(this.anchorCls);
32540
32541             if(this.targetCounter < 2){
32542                 if(axy[0] < scrollX){
32543                     if(this.anchorToTarget){
32544                         this.defaultAlign = 'l-r';
32545                         if(this.mouseOffset){this.mouseOffset[0] *= -1;}
32546                     }
32547                     this.anchor = 'left';
32548                     return this.getTargetXY();
32549                 }
32550                 if(axy[0]+sz.width > dw){
32551                     if(this.anchorToTarget){
32552                         this.defaultAlign = 'r-l';
32553                         if(this.mouseOffset){this.mouseOffset[0] *= -1;}
32554                     }
32555                     this.anchor = 'right';
32556                     return this.getTargetXY();
32557                 }
32558                 if(axy[1] < scrollY){
32559                     if(this.anchorToTarget){
32560                         this.defaultAlign = 't-b';
32561                         if(this.mouseOffset){this.mouseOffset[1] *= -1;}
32562                     }
32563                     this.anchor = 'top';
32564                     return this.getTargetXY();
32565                 }
32566                 if(axy[1]+sz.height > dh){
32567                     if(this.anchorToTarget){
32568                         this.defaultAlign = 'b-t';
32569                         if(this.mouseOffset){this.mouseOffset[1] *= -1;}
32570                     }
32571                     this.anchor = 'bottom';
32572                     return this.getTargetXY();
32573                 }
32574             }
32575
32576             this.anchorCls = 'x-tip-anchor-'+this.getAnchorPosition();
32577             this.anchorEl.addClass(this.anchorCls);
32578             this.targetCounter = 0;
32579             return axy;
32580         }else{
32581             var mouseOffset = this.getMouseOffset();
32582             return [this.targetXY[0]+mouseOffset[0], this.targetXY[1]+mouseOffset[1]];
32583         }
32584     },
32585
32586     getMouseOffset : function(){
32587         var offset = this.anchor ? [0,0] : [15,18];
32588         if(this.mouseOffset){
32589             offset[0] += this.mouseOffset[0];
32590             offset[1] += this.mouseOffset[1];
32591         }
32592         return offset;
32593     },
32594
32595     
32596     getAnchorPosition : function(){
32597         if(this.anchor){
32598             this.tipAnchor = this.anchor.charAt(0);
32599         }else{
32600             var m = this.defaultAlign.match(/^([a-z]+)-([a-z]+)(\?)?$/);
32601             if(!m){
32602                throw 'AnchorTip.defaultAlign is invalid';
32603             }
32604             this.tipAnchor = m[1].charAt(0);
32605         }
32606
32607         switch(this.tipAnchor){
32608             case 't': return 'top';
32609             case 'b': return 'bottom';
32610             case 'r': return 'right';
32611         }
32612         return 'left';
32613     },
32614
32615     
32616     getAnchorAlign : function(){
32617         switch(this.anchor){
32618             case 'top'  : return 'tl-bl';
32619             case 'left' : return 'tl-tr';
32620             case 'right': return 'tr-tl';
32621             default     : return 'bl-tl';
32622         }
32623     },
32624
32625     
32626     getOffsets : function(){
32627         var offsets, 
32628             ap = this.getAnchorPosition().charAt(0);
32629         if(this.anchorToTarget && !this.trackMouse){
32630             switch(ap){
32631                 case 't':
32632                     offsets = [0, 9];
32633                     break;
32634                 case 'b':
32635                     offsets = [0, -13];
32636                     break;
32637                 case 'r':
32638                     offsets = [-13, 0];
32639                     break;
32640                 default:
32641                     offsets = [9, 0];
32642                     break;
32643             }
32644         }else{
32645             switch(ap){
32646                 case 't':
32647                     offsets = [-15-this.anchorOffset, 30];
32648                     break;
32649                 case 'b':
32650                     offsets = [-19-this.anchorOffset, -13-this.el.dom.offsetHeight];
32651                     break;
32652                 case 'r':
32653                     offsets = [-15-this.el.dom.offsetWidth, -13-this.anchorOffset];
32654                     break;
32655                 default:
32656                     offsets = [25, -13-this.anchorOffset];
32657                     break;
32658             }
32659         }
32660         var mouseOffset = this.getMouseOffset();
32661         offsets[0] += mouseOffset[0];
32662         offsets[1] += mouseOffset[1];
32663
32664         return offsets;
32665     },
32666
32667     
32668     onTargetOver : function(e){
32669         if(this.disabled || e.within(this.target.dom, true)){
32670             return;
32671         }
32672         var t = e.getTarget(this.delegate);
32673         if (t) {
32674             this.triggerElement = t;
32675             this.clearTimer('hide');
32676             this.targetXY = e.getXY();
32677             this.delayShow();
32678         }
32679     },
32680
32681     
32682     delayShow : function(){
32683         if(this.hidden && !this.showTimer){
32684             if(this.lastActive.getElapsed() < this.quickShowInterval){
32685                 this.show();
32686             }else{
32687                 this.showTimer = this.show.defer(this.showDelay, this);
32688             }
32689         }else if(!this.hidden && this.autoHide !== false){
32690             this.show();
32691         }
32692     },
32693
32694     
32695     onTargetOut : function(e){
32696         if(this.disabled || e.within(this.target.dom, true)){
32697             return;
32698         }
32699         this.clearTimer('show');
32700         if(this.autoHide !== false){
32701             this.delayHide();
32702         }
32703     },
32704
32705     
32706     delayHide : function(){
32707         if(!this.hidden && !this.hideTimer){
32708             this.hideTimer = this.hide.defer(this.hideDelay, this);
32709         }
32710     },
32711
32712     
32713     hide: function(){
32714         this.clearTimer('dismiss');
32715         this.lastActive = new Date();
32716         if(this.anchorEl){
32717             this.anchorEl.hide();
32718         }
32719         Ext.ToolTip.superclass.hide.call(this);
32720         delete this.triggerElement;
32721     },
32722
32723     
32724     show : function(){
32725         if(this.anchor){
32726             
32727             
32728             this.showAt([-1000,-1000]);
32729             this.origConstrainPosition = this.constrainPosition;
32730             this.constrainPosition = false;
32731             this.anchor = this.origAnchor;
32732         }
32733         this.showAt(this.getTargetXY());
32734
32735         if(this.anchor){
32736             this.anchorEl.show();
32737             this.syncAnchor();
32738             this.constrainPosition = this.origConstrainPosition;
32739         }else{
32740             this.anchorEl.hide();
32741         }
32742     },
32743
32744     
32745     showAt : function(xy){
32746         this.lastActive = new Date();
32747         this.clearTimers();
32748         Ext.ToolTip.superclass.showAt.call(this, xy);
32749         if(this.dismissDelay && this.autoHide !== false){
32750             this.dismissTimer = this.hide.defer(this.dismissDelay, this);
32751         }
32752         if(this.anchor && !this.anchorEl.isVisible()){
32753             this.syncAnchor();
32754             this.anchorEl.show();
32755         }else{
32756             this.anchorEl.hide();
32757         }
32758     },
32759
32760     
32761     syncAnchor : function(){
32762         var anchorPos, targetPos, offset;
32763         switch(this.tipAnchor.charAt(0)){
32764             case 't':
32765                 anchorPos = 'b';
32766                 targetPos = 'tl';
32767                 offset = [20+this.anchorOffset, 2];
32768                 break;
32769             case 'r':
32770                 anchorPos = 'l';
32771                 targetPos = 'tr';
32772                 offset = [-2, 11+this.anchorOffset];
32773                 break;
32774             case 'b':
32775                 anchorPos = 't';
32776                 targetPos = 'bl';
32777                 offset = [20+this.anchorOffset, -2];
32778                 break;
32779             default:
32780                 anchorPos = 'r';
32781                 targetPos = 'tl';
32782                 offset = [2, 11+this.anchorOffset];
32783                 break;
32784         }
32785         this.anchorEl.alignTo(this.el, anchorPos+'-'+targetPos, offset);
32786     },
32787
32788     
32789     setPagePosition : function(x, y){
32790         Ext.ToolTip.superclass.setPagePosition.call(this, x, y);
32791         if(this.anchor){
32792             this.syncAnchor();
32793         }
32794     },
32795
32796     
32797     clearTimer : function(name){
32798         name = name + 'Timer';
32799         clearTimeout(this[name]);
32800         delete this[name];
32801     },
32802
32803     
32804     clearTimers : function(){
32805         this.clearTimer('show');
32806         this.clearTimer('dismiss');
32807         this.clearTimer('hide');
32808     },
32809
32810     
32811     onShow : function(){
32812         Ext.ToolTip.superclass.onShow.call(this);
32813         Ext.getDoc().on('mousedown', this.onDocMouseDown, this);
32814     },
32815
32816     
32817     onHide : function(){
32818         Ext.ToolTip.superclass.onHide.call(this);
32819         Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
32820     },
32821
32822     
32823     onDocMouseDown : function(e){
32824         if(this.autoHide !== true && !this.closable && !e.within(this.el.dom)){
32825             this.disable();
32826             this.doEnable.defer(100, this);
32827         }
32828     },
32829     
32830     
32831     doEnable : function(){
32832         if(!this.isDestroyed){
32833             this.enable();
32834         }
32835     },
32836
32837     
32838     onDisable : function(){
32839         this.clearTimers();
32840         this.hide();
32841     },
32842
32843     
32844     adjustPosition : function(x, y){
32845         if(this.contstrainPosition){
32846             var ay = this.targetXY[1], h = this.getSize().height;
32847             if(y <= ay && (y+h) >= ay){
32848                 y = ay-h-5;
32849             }
32850         }
32851         return {x : x, y: y};
32852     },
32853     
32854     beforeDestroy : function(){
32855         this.clearTimers();
32856         Ext.destroy(this.anchorEl);
32857         delete this.anchorEl;
32858         delete this.target;
32859         delete this.anchorTarget;
32860         delete this.triggerElement;
32861         Ext.ToolTip.superclass.beforeDestroy.call(this);    
32862     },
32863
32864     
32865     onDestroy : function(){
32866         Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
32867         Ext.ToolTip.superclass.onDestroy.call(this);
32868     }
32869 });
32870
32871 Ext.reg('tooltip', Ext.ToolTip);
32872 Ext.QuickTip = Ext.extend(Ext.ToolTip, {
32873     
32874     
32875     interceptTitles : false,
32876
32877     
32878     tagConfig : {
32879         namespace : "ext",
32880         attribute : "qtip",
32881         width : "qwidth",
32882         target : "target",
32883         title : "qtitle",
32884         hide : "hide",
32885         cls : "qclass",
32886         align : "qalign",
32887         anchor : "anchor"
32888     },
32889
32890     
32891     initComponent : function(){
32892         this.target = this.target || Ext.getDoc();
32893         this.targets = this.targets || {};
32894         Ext.QuickTip.superclass.initComponent.call(this);
32895     },
32896
32897     
32898     register : function(config){
32899         var cs = Ext.isArray(config) ? config : arguments;
32900         for(var i = 0, len = cs.length; i < len; i++){
32901             var c = cs[i];
32902             var target = c.target;
32903             if(target){
32904                 if(Ext.isArray(target)){
32905                     for(var j = 0, jlen = target.length; j < jlen; j++){
32906                         this.targets[Ext.id(target[j])] = c;
32907                     }
32908                 } else{
32909                     this.targets[Ext.id(target)] = c;
32910                 }
32911             }
32912         }
32913     },
32914
32915     
32916     unregister : function(el){
32917         delete this.targets[Ext.id(el)];
32918     },
32919     
32920     
32921     cancelShow: function(el){
32922         var at = this.activeTarget;
32923         el = Ext.get(el).dom;
32924         if(this.isVisible()){
32925             if(at && at.el == el){
32926                 this.hide();
32927             }
32928         }else if(at && at.el == el){
32929             this.clearTimer('show');
32930         }
32931     },
32932     
32933     getTipCfg: function(e) {
32934         var t = e.getTarget(), 
32935             ttp, 
32936             cfg;
32937         if(this.interceptTitles && t.title && Ext.isString(t.title)){
32938             ttp = t.title;
32939             t.qtip = ttp;
32940             t.removeAttribute("title");
32941             e.preventDefault();
32942         }else{
32943             cfg = this.tagConfig;
32944             ttp = t.qtip || Ext.fly(t).getAttribute(cfg.attribute, cfg.namespace);
32945         }
32946         return ttp;
32947     },
32948
32949     
32950     onTargetOver : function(e){
32951         if(this.disabled){
32952             return;
32953         }
32954         this.targetXY = e.getXY();
32955         var t = e.getTarget();
32956         if(!t || t.nodeType !== 1 || t == document || t == document.body){
32957             return;
32958         }
32959         if(this.activeTarget && ((t == this.activeTarget.el) || Ext.fly(this.activeTarget.el).contains(t))){
32960             this.clearTimer('hide');
32961             this.show();
32962             return;
32963         }
32964         if(t && this.targets[t.id]){
32965             this.activeTarget = this.targets[t.id];
32966             this.activeTarget.el = t;
32967             this.anchor = this.activeTarget.anchor;
32968             if(this.anchor){
32969                 this.anchorTarget = t;
32970             }
32971             this.delayShow();
32972             return;
32973         }
32974         var ttp, et = Ext.fly(t), cfg = this.tagConfig, ns = cfg.namespace;
32975         if(ttp = this.getTipCfg(e)){
32976             var autoHide = et.getAttribute(cfg.hide, ns);
32977             this.activeTarget = {
32978                 el: t,
32979                 text: ttp,
32980                 width: et.getAttribute(cfg.width, ns),
32981                 autoHide: autoHide != "user" && autoHide !== 'false',
32982                 title: et.getAttribute(cfg.title, ns),
32983                 cls: et.getAttribute(cfg.cls, ns),
32984                 align: et.getAttribute(cfg.align, ns)
32985                 
32986             };
32987             this.anchor = et.getAttribute(cfg.anchor, ns);
32988             if(this.anchor){
32989                 this.anchorTarget = t;
32990             }
32991             this.delayShow();
32992         }
32993     },
32994
32995     
32996     onTargetOut : function(e){
32997
32998         
32999         if (this.activeTarget && e.within(this.activeTarget.el) && !this.getTipCfg(e)) {
33000             return;
33001         }
33002
33003         this.clearTimer('show');
33004         if(this.autoHide !== false){
33005             this.delayHide();
33006         }
33007     },
33008
33009     
33010     showAt : function(xy){
33011         var t = this.activeTarget;
33012         if(t){
33013             if(!this.rendered){
33014                 this.render(Ext.getBody());
33015                 this.activeTarget = t;
33016             }
33017             if(t.width){
33018                 this.setWidth(t.width);
33019                 this.body.setWidth(this.adjustBodyWidth(t.width - this.getFrameWidth()));
33020                 this.measureWidth = false;
33021             } else{
33022                 this.measureWidth = true;
33023             }
33024             this.setTitle(t.title || '');
33025             this.body.update(t.text);
33026             this.autoHide = t.autoHide;
33027             this.dismissDelay = t.dismissDelay || this.dismissDelay;
33028             if(this.lastCls){
33029                 this.el.removeClass(this.lastCls);
33030                 delete this.lastCls;
33031             }
33032             if(t.cls){
33033                 this.el.addClass(t.cls);
33034                 this.lastCls = t.cls;
33035             }
33036             if(this.anchor){
33037                 this.constrainPosition = false;
33038             }else if(t.align){ 
33039                 xy = this.el.getAlignToXY(t.el, t.align);
33040                 this.constrainPosition = false;
33041             }else{
33042                 this.constrainPosition = true;
33043             }
33044         }
33045         Ext.QuickTip.superclass.showAt.call(this, xy);
33046     },
33047
33048     
33049     hide: function(){
33050         delete this.activeTarget;
33051         Ext.QuickTip.superclass.hide.call(this);
33052     }
33053 });
33054 Ext.reg('quicktip', Ext.QuickTip);
33055 Ext.QuickTips = function(){
33056     var tip,
33057         disabled = false;
33058         
33059     return {
33060         
33061         init : function(autoRender){
33062             if(!tip){
33063                 if(!Ext.isReady){
33064                     Ext.onReady(function(){
33065                         Ext.QuickTips.init(autoRender);
33066                     });
33067                     return;
33068                 }
33069                 tip = new Ext.QuickTip({
33070                     elements:'header,body', 
33071                     disabled: disabled
33072                 });
33073                 if(autoRender !== false){
33074                     tip.render(Ext.getBody());
33075                 }
33076             }
33077         },
33078         
33079         
33080         ddDisable : function(){
33081             
33082             if(tip && !disabled){
33083                 tip.disable();
33084             }    
33085         },
33086         
33087         
33088         ddEnable : function(){
33089             
33090             if(tip && !disabled){
33091                 tip.enable();
33092             }
33093         },
33094
33095         
33096         enable : function(){
33097             if(tip){
33098                 tip.enable();
33099             }
33100             disabled = false;
33101         },
33102
33103         
33104         disable : function(){
33105             if(tip){
33106                 tip.disable();
33107             }
33108             disabled = true;
33109         },
33110
33111         
33112         isEnabled : function(){
33113             return tip !== undefined && !tip.disabled;
33114         },
33115
33116         
33117         getQuickTip : function(){
33118             return tip;
33119         },
33120
33121         
33122         register : function(){
33123             tip.register.apply(tip, arguments);
33124         },
33125
33126         
33127         unregister : function(){
33128             tip.unregister.apply(tip, arguments);
33129         },
33130
33131         
33132         tips : function(){
33133             tip.register.apply(tip, arguments);
33134         }
33135     };
33136 }();
33137 Ext.slider.Tip = Ext.extend(Ext.Tip, {
33138     minWidth: 10,
33139     offsets : [0, -10],
33140     
33141     init: function(slider) {
33142         slider.on({
33143             scope    : this,
33144             dragstart: this.onSlide,
33145             drag     : this.onSlide,
33146             dragend  : this.hide,
33147             destroy  : this.destroy
33148         });
33149     },
33150     
33151     
33152     onSlide : function(slider, e, thumb) {
33153         this.show();
33154         this.body.update(this.getText(thumb));
33155         this.doAutoWidth();
33156         this.el.alignTo(thumb.el, 'b-t?', this.offsets);
33157     },
33158
33159     
33160     getText : function(thumb) {
33161         return String(thumb.value);
33162     }
33163 });
33164
33165
33166 Ext.ux.SliderTip = Ext.slider.Tip;
33167 Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
33168     rootVisible : true,
33169     animate : Ext.enableFx,
33170     lines : true,
33171     enableDD : false,
33172     hlDrop : Ext.enableFx,
33173     pathSeparator : '/',
33174
33175     
33176     bubbleEvents : [],
33177
33178     initComponent : function(){
33179         Ext.tree.TreePanel.superclass.initComponent.call(this);
33180
33181         if(!this.eventModel){
33182             this.eventModel = new Ext.tree.TreeEventModel(this);
33183         }
33184
33185         
33186         var l = this.loader;
33187         if(!l){
33188             l = new Ext.tree.TreeLoader({
33189                 dataUrl: this.dataUrl,
33190                 requestMethod: this.requestMethod
33191             });
33192         }else if(Ext.isObject(l) && !l.load){
33193             l = new Ext.tree.TreeLoader(l);
33194         }
33195         this.loader = l;
33196
33197         this.nodeHash = {};
33198
33199         
33200         if(this.root){
33201             var r = this.root;
33202             delete this.root;
33203             this.setRootNode(r);
33204         }
33205
33206
33207         this.addEvents(
33208
33209             
33210            'append',
33211            
33212            'remove',
33213            
33214            'movenode',
33215            
33216            'insert',
33217            
33218            'beforeappend',
33219            
33220            'beforeremove',
33221            
33222            'beforemovenode',
33223            
33224             'beforeinsert',
33225
33226             
33227             'beforeload',
33228             
33229             'load',
33230             
33231             'textchange',
33232             
33233             'beforeexpandnode',
33234             
33235             'beforecollapsenode',
33236             
33237             'expandnode',
33238             
33239             'disabledchange',
33240             
33241             'collapsenode',
33242             
33243             'beforeclick',
33244             
33245             'click',
33246             
33247             'containerclick',
33248             
33249             'checkchange',
33250             
33251             'beforedblclick',
33252             
33253             'dblclick',
33254             
33255             'containerdblclick',
33256             
33257             'contextmenu',
33258             
33259             'containercontextmenu',
33260             
33261             'beforechildrenrendered',
33262            
33263             'startdrag',
33264             
33265             'enddrag',
33266             
33267             'dragdrop',
33268             
33269             'beforenodedrop',
33270             
33271             'nodedrop',
33272              
33273             'nodedragover'
33274         );
33275         if(this.singleExpand){
33276             this.on('beforeexpandnode', this.restrictExpand, this);
33277         }
33278     },
33279
33280     
33281     proxyNodeEvent : function(ename, a1, a2, a3, a4, a5, a6){
33282         if(ename == 'collapse' || ename == 'expand' || ename == 'beforecollapse' || ename == 'beforeexpand' || ename == 'move' || ename == 'beforemove'){
33283             ename = ename+'node';
33284         }
33285         
33286         return this.fireEvent(ename, a1, a2, a3, a4, a5, a6);
33287     },
33288
33289
33290     
33291     getRootNode : function(){
33292         return this.root;
33293     },
33294
33295     
33296     setRootNode : function(node){
33297         this.destroyRoot();
33298         if(!node.render){ 
33299             node = this.loader.createNode(node);
33300         }
33301         this.root = node;
33302         node.ownerTree = this;
33303         node.isRoot = true;
33304         this.registerNode(node);
33305         if(!this.rootVisible){
33306             var uiP = node.attributes.uiProvider;
33307             node.ui = uiP ? new uiP(node) : new Ext.tree.RootTreeNodeUI(node);
33308         }
33309         if(this.innerCt){
33310             this.clearInnerCt();
33311             this.renderRoot();
33312         }
33313         return node;
33314     },
33315     
33316     clearInnerCt : function(){
33317         this.innerCt.update('');    
33318     },
33319     
33320     
33321     renderRoot : function(){
33322         this.root.render();
33323         if(!this.rootVisible){
33324             this.root.renderChildren();
33325         }
33326     },
33327
33328     
33329     getNodeById : function(id){
33330         return this.nodeHash[id];
33331     },
33332
33333     
33334     registerNode : function(node){
33335         this.nodeHash[node.id] = node;
33336     },
33337
33338     
33339     unregisterNode : function(node){
33340         delete this.nodeHash[node.id];
33341     },
33342
33343     
33344     toString : function(){
33345         return '[Tree'+(this.id?' '+this.id:'')+']';
33346     },
33347
33348     
33349     restrictExpand : function(node){
33350         var p = node.parentNode;
33351         if(p){
33352             if(p.expandedChild && p.expandedChild.parentNode == p){
33353                 p.expandedChild.collapse();
33354             }
33355             p.expandedChild = node;
33356         }
33357     },
33358
33359     
33360     getChecked : function(a, startNode){
33361         startNode = startNode || this.root;
33362         var r = [];
33363         var f = function(){
33364             if(this.attributes.checked){
33365                 r.push(!a ? this : (a == 'id' ? this.id : this.attributes[a]));
33366             }
33367         };
33368         startNode.cascade(f);
33369         return r;
33370     },
33371
33372     
33373     getLoader : function(){
33374         return this.loader;
33375     },
33376
33377     
33378     expandAll : function(){
33379         this.root.expand(true);
33380     },
33381
33382     
33383     collapseAll : function(){
33384         this.root.collapse(true);
33385     },
33386
33387     
33388     getSelectionModel : function(){
33389         if(!this.selModel){
33390             this.selModel = new Ext.tree.DefaultSelectionModel();
33391         }
33392         return this.selModel;
33393     },
33394
33395     
33396     expandPath : function(path, attr, callback){
33397         if(Ext.isEmpty(path)){
33398             if(callback){
33399                 callback(false, undefined);
33400             }
33401             return;
33402         }
33403         attr = attr || 'id';
33404         var keys = path.split(this.pathSeparator);
33405         var curNode = this.root;
33406         if(curNode.attributes[attr] != keys[1]){ 
33407             if(callback){
33408                 callback(false, null);
33409             }
33410             return;
33411         }
33412         var index = 1;
33413         var f = function(){
33414             if(++index == keys.length){
33415                 if(callback){
33416                     callback(true, curNode);
33417                 }
33418                 return;
33419             }
33420             var c = curNode.findChild(attr, keys[index]);
33421             if(!c){
33422                 if(callback){
33423                     callback(false, curNode);
33424                 }
33425                 return;
33426             }
33427             curNode = c;
33428             c.expand(false, false, f);
33429         };
33430         curNode.expand(false, false, f);
33431     },
33432
33433     
33434     selectPath : function(path, attr, callback){
33435         if(Ext.isEmpty(path)){
33436             if(callback){
33437                 callback(false, undefined);
33438             }
33439             return;
33440         }
33441         attr = attr || 'id';
33442         var keys = path.split(this.pathSeparator),
33443             v = keys.pop();
33444         if(keys.length > 1){
33445             var f = function(success, node){
33446                 if(success && node){
33447                     var n = node.findChild(attr, v);
33448                     if(n){
33449                         n.select();
33450                         if(callback){
33451                             callback(true, n);
33452                         }
33453                     }else if(callback){
33454                         callback(false, n);
33455                     }
33456                 }else{
33457                     if(callback){
33458                         callback(false, n);
33459                     }
33460                 }
33461             };
33462             this.expandPath(keys.join(this.pathSeparator), attr, f);
33463         }else{
33464             this.root.select();
33465             if(callback){
33466                 callback(true, this.root);
33467             }
33468         }
33469     },
33470
33471     
33472     getTreeEl : function(){
33473         return this.body;
33474     },
33475
33476     
33477     onRender : function(ct, position){
33478         Ext.tree.TreePanel.superclass.onRender.call(this, ct, position);
33479         this.el.addClass('x-tree');
33480         this.innerCt = this.body.createChild({tag:'ul',
33481                cls:'x-tree-root-ct ' +
33482                (this.useArrows ? 'x-tree-arrows' : this.lines ? 'x-tree-lines' : 'x-tree-no-lines')});
33483     },
33484
33485     
33486     initEvents : function(){
33487         Ext.tree.TreePanel.superclass.initEvents.call(this);
33488
33489         if(this.containerScroll){
33490             Ext.dd.ScrollManager.register(this.body);
33491         }
33492         if((this.enableDD || this.enableDrop) && !this.dropZone){
33493            
33494              this.dropZone = new Ext.tree.TreeDropZone(this, this.dropConfig || {
33495                ddGroup: this.ddGroup || 'TreeDD', appendOnly: this.ddAppendOnly === true
33496            });
33497         }
33498         if((this.enableDD || this.enableDrag) && !this.dragZone){
33499            
33500             this.dragZone = new Ext.tree.TreeDragZone(this, this.dragConfig || {
33501                ddGroup: this.ddGroup || 'TreeDD',
33502                scroll: this.ddScroll
33503            });
33504         }
33505         this.getSelectionModel().init(this);
33506     },
33507
33508     
33509     afterRender : function(){
33510         Ext.tree.TreePanel.superclass.afterRender.call(this);
33511         this.renderRoot();
33512     },
33513
33514     beforeDestroy : function(){
33515         if(this.rendered){
33516             Ext.dd.ScrollManager.unregister(this.body);
33517             Ext.destroy(this.dropZone, this.dragZone);
33518         }
33519         this.destroyRoot();
33520         Ext.destroy(this.loader);
33521         this.nodeHash = this.root = this.loader = null;
33522         Ext.tree.TreePanel.superclass.beforeDestroy.call(this);
33523     },
33524     
33525     
33526     destroyRoot : function(){
33527         if(this.root && this.root.destroy){
33528             this.root.destroy(true);
33529         }
33530     }
33531
33532     
33533     
33534     
33535     
33536     
33537     
33538     
33539     
33540     
33541     
33542     
33543     
33544     
33545     
33546     
33547     
33548     
33549     
33550     
33551     
33552     
33553     
33554     
33555     
33556     
33557     
33558     
33559     
33560     
33561     
33562     
33563
33564
33565
33566     
33567     
33568     
33569     
33570     
33571     
33572     
33573     
33574     
33575     
33576     
33577     
33578     
33579     
33580     
33581     
33582 });
33583
33584 Ext.tree.TreePanel.nodeTypes = {};
33585
33586 Ext.reg('treepanel', Ext.tree.TreePanel);Ext.tree.TreeEventModel = function(tree){
33587     this.tree = tree;
33588     this.tree.on('render', this.initEvents, this);
33589 };
33590
33591 Ext.tree.TreeEventModel.prototype = {
33592     initEvents : function(){
33593         var t = this.tree;
33594
33595         if(t.trackMouseOver !== false){
33596             t.mon(t.innerCt, {
33597                 scope: this,
33598                 mouseover: this.delegateOver,
33599                 mouseout: this.delegateOut
33600             });
33601         }
33602         t.mon(t.getTreeEl(), {
33603             scope: this,
33604             click: this.delegateClick,
33605             dblclick: this.delegateDblClick,
33606             contextmenu: this.delegateContextMenu
33607         });
33608     },
33609
33610     getNode : function(e){
33611         var t;
33612         if(t = e.getTarget('.x-tree-node-el', 10)){
33613             var id = Ext.fly(t, '_treeEvents').getAttribute('tree-node-id', 'ext');
33614             if(id){
33615                 return this.tree.getNodeById(id);
33616             }
33617         }
33618         return null;
33619     },
33620
33621     getNodeTarget : function(e){
33622         var t = e.getTarget('.x-tree-node-icon', 1);
33623         if(!t){
33624             t = e.getTarget('.x-tree-node-el', 6);
33625         }
33626         return t;
33627     },
33628
33629     delegateOut : function(e, t){
33630         if(!this.beforeEvent(e)){
33631             return;
33632         }
33633         if(e.getTarget('.x-tree-ec-icon', 1)){
33634             var n = this.getNode(e);
33635             this.onIconOut(e, n);
33636             if(n == this.lastEcOver){
33637                 delete this.lastEcOver;
33638             }
33639         }
33640         if((t = this.getNodeTarget(e)) && !e.within(t, true)){
33641             this.onNodeOut(e, this.getNode(e));
33642         }
33643     },
33644
33645     delegateOver : function(e, t){
33646         if(!this.beforeEvent(e)){
33647             return;
33648         }
33649         if(Ext.isGecko && !this.trackingDoc){ 
33650             Ext.getBody().on('mouseover', this.trackExit, this);
33651             this.trackingDoc = true;
33652         }
33653         if(this.lastEcOver){ 
33654             this.onIconOut(e, this.lastEcOver);
33655             delete this.lastEcOver;
33656         }
33657         if(e.getTarget('.x-tree-ec-icon', 1)){
33658             this.lastEcOver = this.getNode(e);
33659             this.onIconOver(e, this.lastEcOver);
33660         }
33661         if(t = this.getNodeTarget(e)){
33662             this.onNodeOver(e, this.getNode(e));
33663         }
33664     },
33665
33666     trackExit : function(e){
33667         if(this.lastOverNode){
33668             if(this.lastOverNode.ui && !e.within(this.lastOverNode.ui.getEl())){
33669                 this.onNodeOut(e, this.lastOverNode);
33670             }
33671             delete this.lastOverNode;
33672             Ext.getBody().un('mouseover', this.trackExit, this);
33673             this.trackingDoc = false;
33674         }
33675
33676     },
33677
33678     delegateClick : function(e, t){
33679         if(this.beforeEvent(e)){
33680             if(e.getTarget('input[type=checkbox]', 1)){
33681                 this.onCheckboxClick(e, this.getNode(e));
33682             }else if(e.getTarget('.x-tree-ec-icon', 1)){
33683                 this.onIconClick(e, this.getNode(e));
33684             }else if(this.getNodeTarget(e)){
33685                 this.onNodeClick(e, this.getNode(e));
33686             }
33687         }else{
33688             this.checkContainerEvent(e, 'click');
33689         }
33690     },
33691
33692     delegateDblClick : function(e, t){
33693         if(this.beforeEvent(e)){
33694             if(this.getNodeTarget(e)){
33695                 this.onNodeDblClick(e, this.getNode(e));
33696             }
33697         }else{
33698             this.checkContainerEvent(e, 'dblclick');
33699         }
33700     },
33701
33702     delegateContextMenu : function(e, t){
33703         if(this.beforeEvent(e)){
33704             if(this.getNodeTarget(e)){
33705                 this.onNodeContextMenu(e, this.getNode(e));
33706             }
33707         }else{
33708             this.checkContainerEvent(e, 'contextmenu');
33709         }
33710     },
33711     
33712     checkContainerEvent: function(e, type){
33713         if(this.disabled){
33714             e.stopEvent();
33715             return false;
33716         }
33717         this.onContainerEvent(e, type);    
33718     },
33719
33720     onContainerEvent: function(e, type){
33721         this.tree.fireEvent('container' + type, this.tree, e);
33722     },
33723
33724     onNodeClick : function(e, node){
33725         node.ui.onClick(e);
33726     },
33727
33728     onNodeOver : function(e, node){
33729         this.lastOverNode = node;
33730         node.ui.onOver(e);
33731     },
33732
33733     onNodeOut : function(e, node){
33734         node.ui.onOut(e);
33735     },
33736
33737     onIconOver : function(e, node){
33738         node.ui.addClass('x-tree-ec-over');
33739     },
33740
33741     onIconOut : function(e, node){
33742         node.ui.removeClass('x-tree-ec-over');
33743     },
33744
33745     onIconClick : function(e, node){
33746         node.ui.ecClick(e);
33747     },
33748
33749     onCheckboxClick : function(e, node){
33750         node.ui.onCheckChange(e);
33751     },
33752
33753     onNodeDblClick : function(e, node){
33754         node.ui.onDblClick(e);
33755     },
33756
33757     onNodeContextMenu : function(e, node){
33758         node.ui.onContextMenu(e);
33759     },
33760
33761     beforeEvent : function(e){
33762         var node = this.getNode(e);
33763         if(this.disabled || !node || !node.ui){
33764             e.stopEvent();
33765             return false;
33766         }
33767         return true;
33768     },
33769
33770     disable: function(){
33771         this.disabled = true;
33772     },
33773
33774     enable: function(){
33775         this.disabled = false;
33776     }
33777 };
33778 Ext.tree.DefaultSelectionModel = Ext.extend(Ext.util.Observable, {
33779     
33780     constructor : function(config){
33781         this.selNode = null;
33782    
33783         this.addEvents(
33784             
33785             'selectionchange',
33786
33787             
33788             'beforeselect'
33789         );
33790
33791         Ext.apply(this, config);
33792         Ext.tree.DefaultSelectionModel.superclass.constructor.call(this);    
33793     },
33794     
33795     init : function(tree){
33796         this.tree = tree;
33797         tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
33798         tree.on('click', this.onNodeClick, this);
33799     },
33800     
33801     onNodeClick : function(node, e){
33802         this.select(node);
33803     },
33804     
33805     
33806     select : function(node,  selectNextNode){
33807         
33808         if (!Ext.fly(node.ui.wrap).isVisible() && selectNextNode) {
33809             return selectNextNode.call(this, node);
33810         }
33811         var last = this.selNode;
33812         if(node == last){
33813             node.ui.onSelectedChange(true);
33814         }else if(this.fireEvent('beforeselect', this, node, last) !== false){
33815             if(last && last.ui){
33816                 last.ui.onSelectedChange(false);
33817             }
33818             this.selNode = node;
33819             node.ui.onSelectedChange(true);
33820             this.fireEvent('selectionchange', this, node, last);
33821         }
33822         return node;
33823     },
33824     
33825     
33826     unselect : function(node, silent){
33827         if(this.selNode == node){
33828             this.clearSelections(silent);
33829         }    
33830     },
33831     
33832     
33833     clearSelections : function(silent){
33834         var n = this.selNode;
33835         if(n){
33836             n.ui.onSelectedChange(false);
33837             this.selNode = null;
33838             if(silent !== true){
33839                 this.fireEvent('selectionchange', this, null);
33840             }
33841         }
33842         return n;
33843     },
33844     
33845     
33846     getSelectedNode : function(){
33847         return this.selNode;    
33848     },
33849     
33850     
33851     isSelected : function(node){
33852         return this.selNode == node;  
33853     },
33854
33855     
33856     selectPrevious : function( s){
33857         if(!(s = s || this.selNode || this.lastSelNode)){
33858             return null;
33859         }
33860         
33861         var ps = s.previousSibling;
33862         if(ps){
33863             if(!ps.isExpanded() || ps.childNodes.length < 1){
33864                 return this.select(ps, this.selectPrevious);
33865             } else{
33866                 var lc = ps.lastChild;
33867                 while(lc && lc.isExpanded() && Ext.fly(lc.ui.wrap).isVisible() && lc.childNodes.length > 0){
33868                     lc = lc.lastChild;
33869                 }
33870                 return this.select(lc, this.selectPrevious);
33871             }
33872         } else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){
33873             return this.select(s.parentNode, this.selectPrevious);
33874         }
33875         return null;
33876     },
33877
33878     
33879     selectNext : function( s){
33880         if(!(s = s || this.selNode || this.lastSelNode)){
33881             return null;
33882         }
33883         
33884         if(s.firstChild && s.isExpanded() && Ext.fly(s.ui.wrap).isVisible()){
33885              return this.select(s.firstChild, this.selectNext);
33886          }else if(s.nextSibling){
33887              return this.select(s.nextSibling, this.selectNext);
33888          }else if(s.parentNode){
33889             var newS = null;
33890             s.parentNode.bubble(function(){
33891                 if(this.nextSibling){
33892                     newS = this.getOwnerTree().selModel.select(this.nextSibling, this.selectNext);
33893                     return false;
33894                 }
33895             });
33896             return newS;
33897          }
33898         return null;
33899     },
33900
33901     onKeyDown : function(e){
33902         var s = this.selNode || this.lastSelNode;
33903         
33904         var sm = this;
33905         if(!s){
33906             return;
33907         }
33908         var k = e.getKey();
33909         switch(k){
33910              case e.DOWN:
33911                  e.stopEvent();
33912                  this.selectNext();
33913              break;
33914              case e.UP:
33915                  e.stopEvent();
33916                  this.selectPrevious();
33917              break;
33918              case e.RIGHT:
33919                  e.preventDefault();
33920                  if(s.hasChildNodes()){
33921                      if(!s.isExpanded()){
33922                          s.expand();
33923                      }else if(s.firstChild){
33924                          this.select(s.firstChild, e);
33925                      }
33926                  }
33927              break;
33928              case e.LEFT:
33929                  e.preventDefault();
33930                  if(s.hasChildNodes() && s.isExpanded()){
33931                      s.collapse();
33932                  }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){
33933                      this.select(s.parentNode, e);
33934                  }
33935              break;
33936         };
33937     }
33938 });
33939
33940
33941 Ext.tree.MultiSelectionModel = Ext.extend(Ext.util.Observable, {
33942     
33943     constructor : function(config){
33944         this.selNodes = [];
33945         this.selMap = {};
33946         this.addEvents(
33947             
33948             'selectionchange'
33949         );
33950         Ext.apply(this, config);
33951         Ext.tree.MultiSelectionModel.superclass.constructor.call(this);    
33952     },
33953     
33954     init : function(tree){
33955         this.tree = tree;
33956         tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
33957         tree.on('click', this.onNodeClick, this);
33958     },
33959     
33960     onNodeClick : function(node, e){
33961         if(e.ctrlKey && this.isSelected(node)){
33962             this.unselect(node);
33963         }else{
33964             this.select(node, e, e.ctrlKey);
33965         }
33966     },
33967     
33968     
33969     select : function(node, e, keepExisting){
33970         if(keepExisting !== true){
33971             this.clearSelections(true);
33972         }
33973         if(this.isSelected(node)){
33974             this.lastSelNode = node;
33975             return node;
33976         }
33977         this.selNodes.push(node);
33978         this.selMap[node.id] = node;
33979         this.lastSelNode = node;
33980         node.ui.onSelectedChange(true);
33981         this.fireEvent('selectionchange', this, this.selNodes);
33982         return node;
33983     },
33984     
33985     
33986     unselect : function(node){
33987         if(this.selMap[node.id]){
33988             node.ui.onSelectedChange(false);
33989             var sn = this.selNodes;
33990             var index = sn.indexOf(node);
33991             if(index != -1){
33992                 this.selNodes.splice(index, 1);
33993             }
33994             delete this.selMap[node.id];
33995             this.fireEvent('selectionchange', this, this.selNodes);
33996         }
33997     },
33998     
33999     
34000     clearSelections : function(suppressEvent){
34001         var sn = this.selNodes;
34002         if(sn.length > 0){
34003             for(var i = 0, len = sn.length; i < len; i++){
34004                 sn[i].ui.onSelectedChange(false);
34005             }
34006             this.selNodes = [];
34007             this.selMap = {};
34008             if(suppressEvent !== true){
34009                 this.fireEvent('selectionchange', this, this.selNodes);
34010             }
34011         }
34012     },
34013     
34014     
34015     isSelected : function(node){
34016         return this.selMap[node.id] ? true : false;  
34017     },
34018     
34019     
34020     getSelectedNodes : function(){
34021         return this.selNodes.concat([]);
34022     },
34023
34024     onKeyDown : Ext.tree.DefaultSelectionModel.prototype.onKeyDown,
34025
34026     selectNext : Ext.tree.DefaultSelectionModel.prototype.selectNext,
34027
34028     selectPrevious : Ext.tree.DefaultSelectionModel.prototype.selectPrevious
34029 });
34030 Ext.data.Tree = Ext.extend(Ext.util.Observable, {
34031     
34032     constructor: function(root){
34033         this.nodeHash = {};
34034         
34035         this.root = null;
34036         if(root){
34037             this.setRootNode(root);
34038         }
34039         this.addEvents(
34040             
34041             "append",
34042             
34043             "remove",
34044             
34045             "move",
34046             
34047             "insert",
34048             
34049             "beforeappend",
34050             
34051             "beforeremove",
34052             
34053             "beforemove",
34054             
34055             "beforeinsert"
34056         );
34057         Ext.data.Tree.superclass.constructor.call(this);        
34058     },
34059     
34060     
34061     pathSeparator: "/",
34062
34063     
34064     proxyNodeEvent : function(){
34065         return this.fireEvent.apply(this, arguments);
34066     },
34067
34068     
34069     getRootNode : function(){
34070         return this.root;
34071     },
34072
34073     
34074     setRootNode : function(node){
34075         this.root = node;
34076         node.ownerTree = this;
34077         node.isRoot = true;
34078         this.registerNode(node);
34079         return node;
34080     },
34081
34082     
34083     getNodeById : function(id){
34084         return this.nodeHash[id];
34085     },
34086
34087     
34088     registerNode : function(node){
34089         this.nodeHash[node.id] = node;
34090     },
34091
34092     
34093     unregisterNode : function(node){
34094         delete this.nodeHash[node.id];
34095     },
34096
34097     toString : function(){
34098         return "[Tree"+(this.id?" "+this.id:"")+"]";
34099     }
34100 });
34101
34102
34103 Ext.data.Node = Ext.extend(Ext.util.Observable, {
34104     
34105     constructor: function(attributes){
34106         
34107         this.attributes = attributes || {};
34108         this.leaf = this.attributes.leaf;
34109         
34110         this.id = this.attributes.id;
34111         if(!this.id){
34112             this.id = Ext.id(null, "xnode-");
34113             this.attributes.id = this.id;
34114         }
34115         
34116         this.childNodes = [];
34117         
34118         this.parentNode = null;
34119         
34120         this.firstChild = null;
34121         
34122         this.lastChild = null;
34123         
34124         this.previousSibling = null;
34125         
34126         this.nextSibling = null;
34127
34128         this.addEvents({
34129             
34130             "append" : true,
34131             
34132             "remove" : true,
34133             
34134             "move" : true,
34135             
34136             "insert" : true,
34137             
34138             "beforeappend" : true,
34139             
34140             "beforeremove" : true,
34141             
34142             "beforemove" : true,
34143              
34144             "beforeinsert" : true
34145         });
34146         this.listeners = this.attributes.listeners;
34147         Ext.data.Node.superclass.constructor.call(this);    
34148     },
34149     
34150     
34151     fireEvent : function(evtName){
34152         
34153         if(Ext.data.Node.superclass.fireEvent.apply(this, arguments) === false){
34154             return false;
34155         }
34156         
34157         var ot = this.getOwnerTree();
34158         if(ot){
34159             if(ot.proxyNodeEvent.apply(ot, arguments) === false){
34160                 return false;
34161             }
34162         }
34163         return true;
34164     },
34165
34166     
34167     isLeaf : function(){
34168         return this.leaf === true;
34169     },
34170
34171     
34172     setFirstChild : function(node){
34173         this.firstChild = node;
34174     },
34175
34176     
34177     setLastChild : function(node){
34178         this.lastChild = node;
34179     },
34180
34181
34182     
34183     isLast : function(){
34184        return (!this.parentNode ? true : this.parentNode.lastChild == this);
34185     },
34186
34187     
34188     isFirst : function(){
34189        return (!this.parentNode ? true : this.parentNode.firstChild == this);
34190     },
34191
34192     
34193     hasChildNodes : function(){
34194         return !this.isLeaf() && this.childNodes.length > 0;
34195     },
34196
34197     
34198     isExpandable : function(){
34199         return this.attributes.expandable || this.hasChildNodes();
34200     },
34201
34202     
34203     appendChild : function(node){
34204         var multi = false;
34205         if(Ext.isArray(node)){
34206             multi = node;
34207         }else if(arguments.length > 1){
34208             multi = arguments;
34209         }
34210         
34211         if(multi){
34212             for(var i = 0, len = multi.length; i < len; i++) {
34213                 this.appendChild(multi[i]);
34214             }
34215         }else{
34216             if(this.fireEvent("beforeappend", this.ownerTree, this, node) === false){
34217                 return false;
34218             }
34219             var index = this.childNodes.length;
34220             var oldParent = node.parentNode;
34221             
34222             if(oldParent){
34223                 if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index) === false){
34224                     return false;
34225                 }
34226                 oldParent.removeChild(node);
34227             }
34228             index = this.childNodes.length;
34229             if(index === 0){
34230                 this.setFirstChild(node);
34231             }
34232             this.childNodes.push(node);
34233             node.parentNode = this;
34234             var ps = this.childNodes[index-1];
34235             if(ps){
34236                 node.previousSibling = ps;
34237                 ps.nextSibling = node;
34238             }else{
34239                 node.previousSibling = null;
34240             }
34241             node.nextSibling = null;
34242             this.setLastChild(node);
34243             node.setOwnerTree(this.getOwnerTree());
34244             this.fireEvent("append", this.ownerTree, this, node, index);
34245             if(oldParent){
34246                 node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
34247             }
34248             return node;
34249         }
34250     },
34251
34252     
34253     removeChild : function(node, destroy){
34254         var index = this.childNodes.indexOf(node);
34255         if(index == -1){
34256             return false;
34257         }
34258         if(this.fireEvent("beforeremove", this.ownerTree, this, node) === false){
34259             return false;
34260         }
34261
34262         
34263         this.childNodes.splice(index, 1);
34264
34265         
34266         if(node.previousSibling){
34267             node.previousSibling.nextSibling = node.nextSibling;
34268         }
34269         if(node.nextSibling){
34270             node.nextSibling.previousSibling = node.previousSibling;
34271         }
34272
34273         
34274         if(this.firstChild == node){
34275             this.setFirstChild(node.nextSibling);
34276         }
34277         if(this.lastChild == node){
34278             this.setLastChild(node.previousSibling);
34279         }
34280
34281         this.fireEvent("remove", this.ownerTree, this, node);
34282         if(destroy){
34283             node.destroy(true);
34284         }else{
34285             node.clear();
34286         }
34287         return node;
34288     },
34289
34290     
34291     clear : function(destroy){
34292         
34293         this.setOwnerTree(null, destroy);
34294         this.parentNode = this.previousSibling = this.nextSibling = null;
34295         if(destroy){
34296             this.firstChild = this.lastChild = null;
34297         }
34298     },
34299
34300     
34301     destroy : function( silent){
34302         
34303         if(silent === true){
34304             this.purgeListeners();
34305             this.clear(true);
34306             Ext.each(this.childNodes, function(n){
34307                 n.destroy(true);
34308             });
34309             this.childNodes = null;
34310         }else{
34311             this.remove(true);
34312         }
34313     },
34314
34315     
34316     insertBefore : function(node, refNode){
34317         if(!refNode){ 
34318             return this.appendChild(node);
34319         }
34320         
34321         if(node == refNode){
34322             return false;
34323         }
34324
34325         if(this.fireEvent("beforeinsert", this.ownerTree, this, node, refNode) === false){
34326             return false;
34327         }
34328         var index = this.childNodes.indexOf(refNode);
34329         var oldParent = node.parentNode;
34330         var refIndex = index;
34331
34332         
34333         if(oldParent == this && this.childNodes.indexOf(node) < index){
34334             refIndex--;
34335         }
34336
34337         
34338         if(oldParent){
34339             if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index, refNode) === false){
34340                 return false;
34341             }
34342             oldParent.removeChild(node);
34343         }
34344         if(refIndex === 0){
34345             this.setFirstChild(node);
34346         }
34347         this.childNodes.splice(refIndex, 0, node);
34348         node.parentNode = this;
34349         var ps = this.childNodes[refIndex-1];
34350         if(ps){
34351             node.previousSibling = ps;
34352             ps.nextSibling = node;
34353         }else{
34354             node.previousSibling = null;
34355         }
34356         node.nextSibling = refNode;
34357         refNode.previousSibling = node;
34358         node.setOwnerTree(this.getOwnerTree());
34359         this.fireEvent("insert", this.ownerTree, this, node, refNode);
34360         if(oldParent){
34361             node.fireEvent("move", this.ownerTree, node, oldParent, this, refIndex, refNode);
34362         }
34363         return node;
34364     },
34365
34366     
34367     remove : function(destroy){
34368         if (this.parentNode) {
34369             this.parentNode.removeChild(this, destroy);
34370         }
34371         return this;
34372     },
34373
34374     
34375     removeAll : function(destroy){
34376         var cn = this.childNodes,
34377             n;
34378         while((n = cn[0])){
34379             this.removeChild(n, destroy);
34380         }
34381         return this;
34382     },
34383
34384     
34385     item : function(index){
34386         return this.childNodes[index];
34387     },
34388
34389     
34390     replaceChild : function(newChild, oldChild){
34391         var s = oldChild ? oldChild.nextSibling : null;
34392         this.removeChild(oldChild);
34393         this.insertBefore(newChild, s);
34394         return oldChild;
34395     },
34396
34397     
34398     indexOf : function(child){
34399         return this.childNodes.indexOf(child);
34400     },
34401
34402     
34403     getOwnerTree : function(){
34404         
34405         if(!this.ownerTree){
34406             var p = this;
34407             while(p){
34408                 if(p.ownerTree){
34409                     this.ownerTree = p.ownerTree;
34410                     break;
34411                 }
34412                 p = p.parentNode;
34413             }
34414         }
34415         return this.ownerTree;
34416     },
34417
34418     
34419     getDepth : function(){
34420         var depth = 0;
34421         var p = this;
34422         while(p.parentNode){
34423             ++depth;
34424             p = p.parentNode;
34425         }
34426         return depth;
34427     },
34428
34429     
34430     setOwnerTree : function(tree, destroy){
34431         
34432         if(tree != this.ownerTree){
34433             if(this.ownerTree){
34434                 this.ownerTree.unregisterNode(this);
34435             }
34436             this.ownerTree = tree;
34437             
34438             if(destroy !== true){
34439                 Ext.each(this.childNodes, function(n){
34440                     n.setOwnerTree(tree);
34441                 });
34442             }
34443             if(tree){
34444                 tree.registerNode(this);
34445             }
34446         }
34447     },
34448
34449     
34450     setId: function(id){
34451         if(id !== this.id){
34452             var t = this.ownerTree;
34453             if(t){
34454                 t.unregisterNode(this);
34455             }
34456             this.id = this.attributes.id = id;
34457             if(t){
34458                 t.registerNode(this);
34459             }
34460             this.onIdChange(id);
34461         }
34462     },
34463
34464     
34465     onIdChange: Ext.emptyFn,
34466
34467     
34468     getPath : function(attr){
34469         attr = attr || "id";
34470         var p = this.parentNode;
34471         var b = [this.attributes[attr]];
34472         while(p){
34473             b.unshift(p.attributes[attr]);
34474             p = p.parentNode;
34475         }
34476         var sep = this.getOwnerTree().pathSeparator;
34477         return sep + b.join(sep);
34478     },
34479
34480     
34481     bubble : function(fn, scope, args){
34482         var p = this;
34483         while(p){
34484             if(fn.apply(scope || p, args || [p]) === false){
34485                 break;
34486             }
34487             p = p.parentNode;
34488         }
34489     },
34490
34491     
34492     cascade : function(fn, scope, args){
34493         if(fn.apply(scope || this, args || [this]) !== false){
34494             var cs = this.childNodes;
34495             for(var i = 0, len = cs.length; i < len; i++) {
34496                 cs[i].cascade(fn, scope, args);
34497             }
34498         }
34499     },
34500
34501     
34502     eachChild : function(fn, scope, args){
34503         var cs = this.childNodes;
34504         for(var i = 0, len = cs.length; i < len; i++) {
34505             if(fn.apply(scope || cs[i], args || [cs[i]]) === false){
34506                 break;
34507             }
34508         }
34509     },
34510
34511     
34512     findChild : function(attribute, value, deep){
34513         return this.findChildBy(function(){
34514             return this.attributes[attribute] == value;
34515         }, null, deep);
34516     },
34517
34518     
34519     findChildBy : function(fn, scope, deep){
34520         var cs = this.childNodes,
34521             len = cs.length,
34522             i = 0,
34523             n,
34524             res;
34525         for(; i < len; i++){
34526             n = cs[i];
34527             if(fn.call(scope || n, n) === true){
34528                 return n;
34529             }else if (deep){
34530                 res = n.findChildBy(fn, scope, deep);
34531                 if(res != null){
34532                     return res;
34533                 }
34534             }
34535             
34536         }
34537         return null;
34538     },
34539
34540     
34541     sort : function(fn, scope){
34542         var cs = this.childNodes;
34543         var len = cs.length;
34544         if(len > 0){
34545             var sortFn = scope ? function(){fn.apply(scope, arguments);} : fn;
34546             cs.sort(sortFn);
34547             for(var i = 0; i < len; i++){
34548                 var n = cs[i];
34549                 n.previousSibling = cs[i-1];
34550                 n.nextSibling = cs[i+1];
34551                 if(i === 0){
34552                     this.setFirstChild(n);
34553                 }
34554                 if(i == len-1){
34555                     this.setLastChild(n);
34556                 }
34557             }
34558         }
34559     },
34560
34561     
34562     contains : function(node){
34563         return node.isAncestor(this);
34564     },
34565
34566     
34567     isAncestor : function(node){
34568         var p = this.parentNode;
34569         while(p){
34570             if(p == node){
34571                 return true;
34572             }
34573             p = p.parentNode;
34574         }
34575         return false;
34576     },
34577
34578     toString : function(){
34579         return "[Node"+(this.id?" "+this.id:"")+"]";
34580     }
34581 });
34582 Ext.tree.TreeNode = Ext.extend(Ext.data.Node, {
34583     
34584     constructor : function(attributes){
34585         attributes = attributes || {};
34586         if(Ext.isString(attributes)){
34587             attributes = {text: attributes};
34588         }
34589         this.childrenRendered = false;
34590         this.rendered = false;
34591         Ext.tree.TreeNode.superclass.constructor.call(this, attributes);
34592         this.expanded = attributes.expanded === true;
34593         this.isTarget = attributes.isTarget !== false;
34594         this.draggable = attributes.draggable !== false && attributes.allowDrag !== false;
34595         this.allowChildren = attributes.allowChildren !== false && attributes.allowDrop !== false;
34596
34597         
34598         this.text = attributes.text;
34599         
34600         this.disabled = attributes.disabled === true;
34601         
34602         this.hidden = attributes.hidden === true;
34603     
34604         this.addEvents(
34605             
34606             'textchange',
34607             
34608             'beforeexpand',
34609             
34610             'beforecollapse',
34611             
34612             'expand',
34613             
34614             'disabledchange',
34615             
34616             'collapse',
34617             
34618             'beforeclick',
34619             
34620             'click',
34621             
34622             'checkchange',
34623             
34624             'beforedblclick',
34625             
34626             'dblclick',
34627             
34628             'contextmenu',
34629             
34630             'beforechildrenrendered'
34631         );
34632     
34633         var uiClass = this.attributes.uiProvider || this.defaultUI || Ext.tree.TreeNodeUI;
34634     
34635         
34636         this.ui = new uiClass(this);    
34637     },
34638     
34639     preventHScroll : true,
34640     
34641     isExpanded : function(){
34642         return this.expanded;
34643     },
34644
34645
34646     getUI : function(){
34647         return this.ui;
34648     },
34649
34650     getLoader : function(){
34651         var owner;
34652         return this.loader || ((owner = this.getOwnerTree()) && owner.loader ? owner.loader : (this.loader = new Ext.tree.TreeLoader()));
34653     },
34654
34655     
34656     setFirstChild : function(node){
34657         var of = this.firstChild;
34658         Ext.tree.TreeNode.superclass.setFirstChild.call(this, node);
34659         if(this.childrenRendered && of && node != of){
34660             of.renderIndent(true, true);
34661         }
34662         if(this.rendered){
34663             this.renderIndent(true, true);
34664         }
34665     },
34666
34667     
34668     setLastChild : function(node){
34669         var ol = this.lastChild;
34670         Ext.tree.TreeNode.superclass.setLastChild.call(this, node);
34671         if(this.childrenRendered && ol && node != ol){
34672             ol.renderIndent(true, true);
34673         }
34674         if(this.rendered){
34675             this.renderIndent(true, true);
34676         }
34677     },
34678
34679     
34680     
34681     appendChild : function(n){
34682         if(!n.render && !Ext.isArray(n)){
34683             n = this.getLoader().createNode(n);
34684         }
34685         var node = Ext.tree.TreeNode.superclass.appendChild.call(this, n);
34686         if(node && this.childrenRendered){
34687             node.render();
34688         }
34689         this.ui.updateExpandIcon();
34690         return node;
34691     },
34692
34693     
34694     removeChild : function(node, destroy){
34695         this.ownerTree.getSelectionModel().unselect(node);
34696         Ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);
34697         
34698         if(!destroy){
34699             var rendered = node.ui.rendered;
34700             
34701             if(rendered){
34702                 node.ui.remove();
34703             }
34704             if(rendered && this.childNodes.length < 1){
34705                 this.collapse(false, false);
34706             }else{
34707                 this.ui.updateExpandIcon();
34708             }
34709             if(!this.firstChild && !this.isHiddenRoot()){
34710                 this.childrenRendered = false;
34711             }
34712         }
34713         return node;
34714     },
34715
34716     
34717     insertBefore : function(node, refNode){
34718         if(!node.render){
34719             node = this.getLoader().createNode(node);
34720         }
34721         var newNode = Ext.tree.TreeNode.superclass.insertBefore.call(this, node, refNode);
34722         if(newNode && refNode && this.childrenRendered){
34723             node.render();
34724         }
34725         this.ui.updateExpandIcon();
34726         return newNode;
34727     },
34728
34729     
34730     setText : function(text){
34731         var oldText = this.text;
34732         this.text = this.attributes.text = text;
34733         if(this.rendered){ 
34734             this.ui.onTextChange(this, text, oldText);
34735         }
34736         this.fireEvent('textchange', this, text, oldText);
34737     },
34738     
34739     
34740     setIconCls : function(cls){
34741         var old = this.attributes.iconCls;
34742         this.attributes.iconCls = cls;
34743         if(this.rendered){
34744             this.ui.onIconClsChange(this, cls, old);
34745         }
34746     },
34747     
34748     
34749     setTooltip : function(tip, title){
34750         this.attributes.qtip = tip;
34751         this.attributes.qtipTitle = title;
34752         if(this.rendered){
34753             this.ui.onTipChange(this, tip, title);
34754         }
34755     },
34756     
34757     
34758     setIcon : function(icon){
34759         this.attributes.icon = icon;
34760         if(this.rendered){
34761             this.ui.onIconChange(this, icon);
34762         }
34763     },
34764     
34765     
34766     setHref : function(href, target){
34767         this.attributes.href = href;
34768         this.attributes.hrefTarget = target;
34769         if(this.rendered){
34770             this.ui.onHrefChange(this, href, target);
34771         }
34772     },
34773     
34774     
34775     setCls : function(cls){
34776         var old = this.attributes.cls;
34777         this.attributes.cls = cls;
34778         if(this.rendered){
34779             this.ui.onClsChange(this, cls, old);
34780         }
34781     },
34782
34783     
34784     select : function(){
34785         var t = this.getOwnerTree();
34786         if(t){
34787             t.getSelectionModel().select(this);
34788         }
34789     },
34790
34791     
34792     unselect : function(silent){
34793         var t = this.getOwnerTree();
34794         if(t){
34795             t.getSelectionModel().unselect(this, silent);
34796         }
34797     },
34798
34799     
34800     isSelected : function(){
34801         var t = this.getOwnerTree();
34802         return t ? t.getSelectionModel().isSelected(this) : false;
34803     },
34804
34805     
34806     expand : function(deep, anim, callback, scope){
34807         if(!this.expanded){
34808             if(this.fireEvent('beforeexpand', this, deep, anim) === false){
34809                 return;
34810             }
34811             if(!this.childrenRendered){
34812                 this.renderChildren();
34813             }
34814             this.expanded = true;
34815             if(!this.isHiddenRoot() && (this.getOwnerTree().animate && anim !== false) || anim){
34816                 this.ui.animExpand(function(){
34817                     this.fireEvent('expand', this);
34818                     this.runCallback(callback, scope || this, [this]);
34819                     if(deep === true){
34820                         this.expandChildNodes(true, true);
34821                     }
34822                 }.createDelegate(this));
34823                 return;
34824             }else{
34825                 this.ui.expand();
34826                 this.fireEvent('expand', this);
34827                 this.runCallback(callback, scope || this, [this]);
34828             }
34829         }else{
34830            this.runCallback(callback, scope || this, [this]);
34831         }
34832         if(deep === true){
34833             this.expandChildNodes(true);
34834         }
34835     },
34836
34837     runCallback : function(cb, scope, args){
34838         if(Ext.isFunction(cb)){
34839             cb.apply(scope, args);
34840         }
34841     },
34842
34843     isHiddenRoot : function(){
34844         return this.isRoot && !this.getOwnerTree().rootVisible;
34845     },
34846
34847     
34848     collapse : function(deep, anim, callback, scope){
34849         if(this.expanded && !this.isHiddenRoot()){
34850             if(this.fireEvent('beforecollapse', this, deep, anim) === false){
34851                 return;
34852             }
34853             this.expanded = false;
34854             if((this.getOwnerTree().animate && anim !== false) || anim){
34855                 this.ui.animCollapse(function(){
34856                     this.fireEvent('collapse', this);
34857                     this.runCallback(callback, scope || this, [this]);
34858                     if(deep === true){
34859                         this.collapseChildNodes(true);
34860                     }
34861                 }.createDelegate(this));
34862                 return;
34863             }else{
34864                 this.ui.collapse();
34865                 this.fireEvent('collapse', this);
34866                 this.runCallback(callback, scope || this, [this]);
34867             }
34868         }else if(!this.expanded){
34869             this.runCallback(callback, scope || this, [this]);
34870         }
34871         if(deep === true){
34872             var cs = this.childNodes;
34873             for(var i = 0, len = cs.length; i < len; i++) {
34874                 cs[i].collapse(true, false);
34875             }
34876         }
34877     },
34878
34879     
34880     delayedExpand : function(delay){
34881         if(!this.expandProcId){
34882             this.expandProcId = this.expand.defer(delay, this);
34883         }
34884     },
34885
34886     
34887     cancelExpand : function(){
34888         if(this.expandProcId){
34889             clearTimeout(this.expandProcId);
34890         }
34891         this.expandProcId = false;
34892     },
34893
34894     
34895     toggle : function(){
34896         if(this.expanded){
34897             this.collapse();
34898         }else{
34899             this.expand();
34900         }
34901     },
34902
34903     
34904     ensureVisible : function(callback, scope){
34905         var tree = this.getOwnerTree();
34906         tree.expandPath(this.parentNode ? this.parentNode.getPath() : this.getPath(), false, function(){
34907             var node = tree.getNodeById(this.id);  
34908             tree.getTreeEl().scrollChildIntoView(node.ui.anchor);
34909             this.runCallback(callback, scope || this, [this]);
34910         }.createDelegate(this));
34911     },
34912
34913     
34914     expandChildNodes : function(deep, anim) {
34915         var cs = this.childNodes,
34916             i,
34917             len = cs.length;
34918         for (i = 0; i < len; i++) {
34919                 cs[i].expand(deep, anim);
34920         }
34921     },
34922
34923     
34924     collapseChildNodes : function(deep){
34925         var cs = this.childNodes;
34926         for(var i = 0, len = cs.length; i < len; i++) {
34927                 cs[i].collapse(deep);
34928         }
34929     },
34930
34931     
34932     disable : function(){
34933         this.disabled = true;
34934         this.unselect();
34935         if(this.rendered && this.ui.onDisableChange){ 
34936             this.ui.onDisableChange(this, true);
34937         }
34938         this.fireEvent('disabledchange', this, true);
34939     },
34940
34941     
34942     enable : function(){
34943         this.disabled = false;
34944         if(this.rendered && this.ui.onDisableChange){ 
34945             this.ui.onDisableChange(this, false);
34946         }
34947         this.fireEvent('disabledchange', this, false);
34948     },
34949
34950     
34951     renderChildren : function(suppressEvent){
34952         if(suppressEvent !== false){
34953             this.fireEvent('beforechildrenrendered', this);
34954         }
34955         var cs = this.childNodes;
34956         for(var i = 0, len = cs.length; i < len; i++){
34957             cs[i].render(true);
34958         }
34959         this.childrenRendered = true;
34960     },
34961
34962     
34963     sort : function(fn, scope){
34964         Ext.tree.TreeNode.superclass.sort.apply(this, arguments);
34965         if(this.childrenRendered){
34966             var cs = this.childNodes;
34967             for(var i = 0, len = cs.length; i < len; i++){
34968                 cs[i].render(true);
34969             }
34970         }
34971     },
34972
34973     
34974     render : function(bulkRender){
34975         this.ui.render(bulkRender);
34976         if(!this.rendered){
34977             
34978             this.getOwnerTree().registerNode(this);
34979             this.rendered = true;
34980             if(this.expanded){
34981                 this.expanded = false;
34982                 this.expand(false, false);
34983             }
34984         }
34985     },
34986
34987     
34988     renderIndent : function(deep, refresh){
34989         if(refresh){
34990             this.ui.childIndent = null;
34991         }
34992         this.ui.renderIndent();
34993         if(deep === true && this.childrenRendered){
34994             var cs = this.childNodes;
34995             for(var i = 0, len = cs.length; i < len; i++){
34996                 cs[i].renderIndent(true, refresh);
34997             }
34998         }
34999     },
35000
35001     beginUpdate : function(){
35002         this.childrenRendered = false;
35003     },
35004
35005     endUpdate : function(){
35006         if(this.expanded && this.rendered){
35007             this.renderChildren();
35008         }
35009     },
35010
35011     
35012     destroy : function(silent){
35013         if(silent === true){
35014             this.unselect(true);
35015         }
35016         Ext.tree.TreeNode.superclass.destroy.call(this, silent);
35017         Ext.destroy(this.ui, this.loader);
35018         this.ui = this.loader = null;
35019     },
35020
35021     
35022     onIdChange : function(id){
35023         this.ui.onIdChange(id);
35024     }
35025 });
35026
35027 Ext.tree.TreePanel.nodeTypes.node = Ext.tree.TreeNode;
35028  Ext.tree.AsyncTreeNode = function(config){
35029     this.loaded = config && config.loaded === true;
35030     this.loading = false;
35031     Ext.tree.AsyncTreeNode.superclass.constructor.apply(this, arguments);
35032     
35033     this.addEvents('beforeload', 'load');
35034     
35035     
35036 };
35037 Ext.extend(Ext.tree.AsyncTreeNode, Ext.tree.TreeNode, {
35038     expand : function(deep, anim, callback, scope){
35039         if(this.loading){ 
35040             var timer;
35041             var f = function(){
35042                 if(!this.loading){ 
35043                     clearInterval(timer);
35044                     this.expand(deep, anim, callback, scope);
35045                 }
35046             }.createDelegate(this);
35047             timer = setInterval(f, 200);
35048             return;
35049         }
35050         if(!this.loaded){
35051             if(this.fireEvent("beforeload", this) === false){
35052                 return;
35053             }
35054             this.loading = true;
35055             this.ui.beforeLoad(this);
35056             var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();
35057             if(loader){
35058                 loader.load(this, this.loadComplete.createDelegate(this, [deep, anim, callback, scope]), this);
35059                 return;
35060             }
35061         }
35062         Ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback, scope);
35063     },
35064     
35065     
35066     isLoading : function(){
35067         return this.loading;  
35068     },
35069     
35070     loadComplete : function(deep, anim, callback, scope){
35071         this.loading = false;
35072         this.loaded = true;
35073         this.ui.afterLoad(this);
35074         this.fireEvent("load", this);
35075         this.expand(deep, anim, callback, scope);
35076     },
35077     
35078     
35079     isLoaded : function(){
35080         return this.loaded;
35081     },
35082     
35083     hasChildNodes : function(){
35084         if(!this.isLeaf() && !this.loaded){
35085             return true;
35086         }else{
35087             return Ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this);
35088         }
35089     },
35090
35091     
35092     reload : function(callback, scope){
35093         this.collapse(false, false);
35094         while(this.firstChild){
35095             this.removeChild(this.firstChild).destroy();
35096         }
35097         this.childrenRendered = false;
35098         this.loaded = false;
35099         if(this.isHiddenRoot()){
35100             this.expanded = false;
35101         }
35102         this.expand(false, false, callback, scope);
35103     }
35104 });
35105
35106 Ext.tree.TreePanel.nodeTypes.async = Ext.tree.AsyncTreeNode;
35107 Ext.tree.TreeNodeUI = Ext.extend(Object, {
35108     
35109     constructor : function(node){
35110         Ext.apply(this, {
35111             node: node,
35112             rendered: false,
35113             animating: false,
35114             wasLeaf: true,
35115             ecc: 'x-tree-ec-icon x-tree-elbow',
35116             emptyIcon: Ext.BLANK_IMAGE_URL    
35117         });
35118     },
35119     
35120     
35121     removeChild : function(node){
35122         if(this.rendered){
35123             this.ctNode.removeChild(node.ui.getEl());
35124         }
35125     },
35126
35127     
35128     beforeLoad : function(){
35129          this.addClass("x-tree-node-loading");
35130     },
35131
35132     
35133     afterLoad : function(){
35134          this.removeClass("x-tree-node-loading");
35135     },
35136
35137     
35138     onTextChange : function(node, text, oldText){
35139         if(this.rendered){
35140             this.textNode.innerHTML = text;
35141         }
35142     },
35143     
35144     
35145     onIconClsChange : function(node, cls, oldCls){
35146         if(this.rendered){
35147             Ext.fly(this.iconNode).replaceClass(oldCls, cls);
35148         }
35149     },
35150     
35151     
35152     onIconChange : function(node, icon){
35153         if(this.rendered){
35154             
35155             var empty = Ext.isEmpty(icon);
35156             this.iconNode.src = empty ? this.emptyIcon : icon;
35157             Ext.fly(this.iconNode)[empty ? 'removeClass' : 'addClass']('x-tree-node-inline-icon');
35158         }
35159     },
35160     
35161     
35162     onTipChange : function(node, tip, title){
35163         if(this.rendered){
35164             var hasTitle = Ext.isDefined(title);
35165             if(this.textNode.setAttributeNS){
35166                 this.textNode.setAttributeNS("ext", "qtip", tip);
35167                 if(hasTitle){
35168                     this.textNode.setAttributeNS("ext", "qtitle", title);
35169                 }
35170             }else{
35171                 this.textNode.setAttribute("ext:qtip", tip);
35172                 if(hasTitle){
35173                     this.textNode.setAttribute("ext:qtitle", title);
35174                 }
35175             }
35176         }
35177     },
35178     
35179     
35180     onHrefChange : function(node, href, target){
35181         if(this.rendered){
35182             this.anchor.href = this.getHref(href);
35183             if(Ext.isDefined(target)){
35184                 this.anchor.target = target;
35185             }
35186         }
35187     },
35188     
35189     
35190     onClsChange : function(node, cls, oldCls){
35191         if(this.rendered){
35192             Ext.fly(this.elNode).replaceClass(oldCls, cls);
35193         }    
35194     },
35195
35196     
35197     onDisableChange : function(node, state){
35198         this.disabled = state;
35199         if (this.checkbox) {
35200             this.checkbox.disabled = state;
35201         }
35202         this[state ? 'addClass' : 'removeClass']('x-tree-node-disabled');
35203     },
35204
35205     
35206     onSelectedChange : function(state){
35207         if(state){
35208             this.focus();
35209             this.addClass("x-tree-selected");
35210         }else{
35211             
35212             this.removeClass("x-tree-selected");
35213         }
35214     },
35215
35216     
35217     onMove : function(tree, node, oldParent, newParent, index, refNode){
35218         this.childIndent = null;
35219         if(this.rendered){
35220             var targetNode = newParent.ui.getContainer();
35221             if(!targetNode){
35222                 this.holder = document.createElement("div");
35223                 this.holder.appendChild(this.wrap);
35224                 return;
35225             }
35226             var insertBefore = refNode ? refNode.ui.getEl() : null;
35227             if(insertBefore){
35228                 targetNode.insertBefore(this.wrap, insertBefore);
35229             }else{
35230                 targetNode.appendChild(this.wrap);
35231             }
35232             this.node.renderIndent(true, oldParent != newParent);
35233         }
35234     },
35235
35236
35237     addClass : function(cls){
35238         if(this.elNode){
35239             Ext.fly(this.elNode).addClass(cls);
35240         }
35241     },
35242
35243
35244     removeClass : function(cls){
35245         if(this.elNode){
35246             Ext.fly(this.elNode).removeClass(cls);
35247         }
35248     },
35249
35250     
35251     remove : function(){
35252         if(this.rendered){
35253             this.holder = document.createElement("div");
35254             this.holder.appendChild(this.wrap);
35255         }
35256     },
35257
35258     
35259     fireEvent : function(){
35260         return this.node.fireEvent.apply(this.node, arguments);
35261     },
35262
35263     
35264     initEvents : function(){
35265         this.node.on("move", this.onMove, this);
35266
35267         if(this.node.disabled){
35268             this.onDisableChange(this.node, true);
35269         }
35270         if(this.node.hidden){
35271             this.hide();
35272         }
35273         var ot = this.node.getOwnerTree();
35274         var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;
35275         if(dd && (!this.node.isRoot || ot.rootVisible)){
35276             Ext.dd.Registry.register(this.elNode, {
35277                 node: this.node,
35278                 handles: this.getDDHandles(),
35279                 isHandle: false
35280             });
35281         }
35282     },
35283
35284     
35285     getDDHandles : function(){
35286         return [this.iconNode, this.textNode, this.elNode];
35287     },
35288
35289
35290     hide : function(){
35291         this.node.hidden = true;
35292         if(this.wrap){
35293             this.wrap.style.display = "none";
35294         }
35295     },
35296
35297
35298     show : function(){
35299         this.node.hidden = false;
35300         if(this.wrap){
35301             this.wrap.style.display = "";
35302         }
35303     },
35304
35305     
35306     onContextMenu : function(e){
35307         if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {
35308             e.preventDefault();
35309             this.focus();
35310             this.fireEvent("contextmenu", this.node, e);
35311         }
35312     },
35313
35314     
35315     onClick : function(e){
35316         if(this.dropping){
35317             e.stopEvent();
35318             return;
35319         }
35320         if(this.fireEvent("beforeclick", this.node, e) !== false){
35321             var a = e.getTarget('a');
35322             if(!this.disabled && this.node.attributes.href && a){
35323                 this.fireEvent("click", this.node, e);
35324                 return;
35325             }else if(a && e.ctrlKey){
35326                 e.stopEvent();
35327             }
35328             e.preventDefault();
35329             if(this.disabled){
35330                 return;
35331             }
35332
35333             if(this.node.attributes.singleClickExpand && !this.animating && this.node.isExpandable()){
35334                 this.node.toggle();
35335             }
35336
35337             this.fireEvent("click", this.node, e);
35338         }else{
35339             e.stopEvent();
35340         }
35341     },
35342
35343     
35344     onDblClick : function(e){
35345         e.preventDefault();
35346         if(this.disabled){
35347             return;
35348         }
35349         if(this.fireEvent("beforedblclick", this.node, e) !== false){
35350             if(this.checkbox){
35351                 this.toggleCheck();
35352             }
35353             if(!this.animating && this.node.isExpandable()){
35354                 this.node.toggle();
35355             }
35356             this.fireEvent("dblclick", this.node, e);
35357         }
35358     },
35359
35360     onOver : function(e){
35361         this.addClass('x-tree-node-over');
35362     },
35363
35364     onOut : function(e){
35365         this.removeClass('x-tree-node-over');
35366     },
35367
35368     
35369     onCheckChange : function(){
35370         var checked = this.checkbox.checked;
35371         
35372         this.checkbox.defaultChecked = checked;
35373         this.node.attributes.checked = checked;
35374         this.fireEvent('checkchange', this.node, checked);
35375     },
35376
35377     
35378     ecClick : function(e){
35379         if(!this.animating && this.node.isExpandable()){
35380             this.node.toggle();
35381         }
35382     },
35383
35384     
35385     startDrop : function(){
35386         this.dropping = true;
35387     },
35388
35389     
35390     endDrop : function(){
35391        setTimeout(function(){
35392            this.dropping = false;
35393        }.createDelegate(this), 50);
35394     },
35395
35396     
35397     expand : function(){
35398         this.updateExpandIcon();
35399         this.ctNode.style.display = "";
35400     },
35401
35402     
35403     focus : function(){
35404         if(!this.node.preventHScroll){
35405             try{this.anchor.focus();
35406             }catch(e){}
35407         }else{
35408             try{
35409                 var noscroll = this.node.getOwnerTree().getTreeEl().dom;
35410                 var l = noscroll.scrollLeft;
35411                 this.anchor.focus();
35412                 noscroll.scrollLeft = l;
35413             }catch(e){}
35414         }
35415     },
35416
35417
35418     toggleCheck : function(value){
35419         var cb = this.checkbox;
35420         if(cb){
35421             cb.checked = (value === undefined ? !cb.checked : value);
35422             this.onCheckChange();
35423         }
35424     },
35425
35426     
35427     blur : function(){
35428         try{
35429             this.anchor.blur();
35430         }catch(e){}
35431     },
35432
35433     
35434     animExpand : function(callback){
35435         var ct = Ext.get(this.ctNode);
35436         ct.stopFx();
35437         if(!this.node.isExpandable()){
35438             this.updateExpandIcon();
35439             this.ctNode.style.display = "";
35440             Ext.callback(callback);
35441             return;
35442         }
35443         this.animating = true;
35444         this.updateExpandIcon();
35445
35446         ct.slideIn('t', {
35447            callback : function(){
35448                this.animating = false;
35449                Ext.callback(callback);
35450             },
35451             scope: this,
35452             duration: this.node.ownerTree.duration || .25
35453         });
35454     },
35455
35456     
35457     highlight : function(){
35458         var tree = this.node.getOwnerTree();
35459         Ext.fly(this.wrap).highlight(
35460             tree.hlColor || "C3DAF9",
35461             {endColor: tree.hlBaseColor}
35462         );
35463     },
35464
35465     
35466     collapse : function(){
35467         this.updateExpandIcon();
35468         this.ctNode.style.display = "none";
35469     },
35470
35471     
35472     animCollapse : function(callback){
35473         var ct = Ext.get(this.ctNode);
35474         ct.enableDisplayMode('block');
35475         ct.stopFx();
35476
35477         this.animating = true;
35478         this.updateExpandIcon();
35479
35480         ct.slideOut('t', {
35481             callback : function(){
35482                this.animating = false;
35483                Ext.callback(callback);
35484             },
35485             scope: this,
35486             duration: this.node.ownerTree.duration || .25
35487         });
35488     },
35489
35490     
35491     getContainer : function(){
35492         return this.ctNode;
35493     },
35494
35495
35496     getEl : function(){
35497         return this.wrap;
35498     },
35499
35500     
35501     appendDDGhost : function(ghostNode){
35502         ghostNode.appendChild(this.elNode.cloneNode(true));
35503     },
35504
35505     
35506     getDDRepairXY : function(){
35507         return Ext.lib.Dom.getXY(this.iconNode);
35508     },
35509
35510     
35511     onRender : function(){
35512         this.render();
35513     },
35514
35515     
35516     render : function(bulkRender){
35517         var n = this.node, a = n.attributes;
35518         var targetNode = n.parentNode ?
35519               n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;
35520
35521         if(!this.rendered){
35522             this.rendered = true;
35523
35524             this.renderElements(n, a, targetNode, bulkRender);
35525
35526             if(a.qtip){
35527                 this.onTipChange(n, a.qtip, a.qtipTitle);
35528             }else if(a.qtipCfg){
35529                 a.qtipCfg.target = Ext.id(this.textNode);
35530                 Ext.QuickTips.register(a.qtipCfg);
35531             }
35532             this.initEvents();
35533             if(!this.node.expanded){
35534                 this.updateExpandIcon(true);
35535             }
35536         }else{
35537             if(bulkRender === true) {
35538                 targetNode.appendChild(this.wrap);
35539             }
35540         }
35541     },
35542
35543     
35544     renderElements : function(n, a, targetNode, bulkRender){
35545         
35546         this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
35547
35548         var cb = Ext.isBoolean(a.checked),
35549             nel,
35550             href = this.getHref(a.href),
35551             buf = ['<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf x-unselectable ', a.cls,'" unselectable="on">',
35552             '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
35553             '<img alt="" src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',
35554             '<img alt="" src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',
35555             cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '',
35556             '<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',
35557              a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span unselectable="on">',n.text,"</span></a></div>",
35558             '<ul class="x-tree-node-ct" style="display:none;"></ul>',
35559             "</li>"].join('');
35560
35561         if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){
35562             this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
35563         }else{
35564             this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
35565         }
35566
35567         this.elNode = this.wrap.childNodes[0];
35568         this.ctNode = this.wrap.childNodes[1];
35569         var cs = this.elNode.childNodes;
35570         this.indentNode = cs[0];
35571         this.ecNode = cs[1];
35572         this.iconNode = cs[2];
35573         var index = 3;
35574         if(cb){
35575             this.checkbox = cs[3];
35576             
35577             this.checkbox.defaultChecked = this.checkbox.checked;
35578             index++;
35579         }
35580         this.anchor = cs[index];
35581         this.textNode = cs[index].firstChild;
35582     },
35583     
35584     
35585     getHref : function(href){
35586         return Ext.isEmpty(href) ? (Ext.isGecko ? '' : '#') : href;
35587     },
35588
35589
35590     getAnchor : function(){
35591         return this.anchor;
35592     },
35593
35594
35595     getTextEl : function(){
35596         return this.textNode;
35597     },
35598
35599
35600     getIconEl : function(){
35601         return this.iconNode;
35602     },
35603
35604
35605     isChecked : function(){
35606         return this.checkbox ? this.checkbox.checked : false;
35607     },
35608
35609     
35610     updateExpandIcon : function(){
35611         if(this.rendered){
35612             var n = this.node,
35613                 c1,
35614                 c2,
35615                 cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow",
35616                 hasChild = n.hasChildNodes();
35617             if(hasChild || n.attributes.expandable){
35618                 if(n.expanded){
35619                     cls += "-minus";
35620                     c1 = "x-tree-node-collapsed";
35621                     c2 = "x-tree-node-expanded";
35622                 }else{
35623                     cls += "-plus";
35624                     c1 = "x-tree-node-expanded";
35625                     c2 = "x-tree-node-collapsed";
35626                 }
35627                 if(this.wasLeaf){
35628                     this.removeClass("x-tree-node-leaf");
35629                     this.wasLeaf = false;
35630                 }
35631                 if(this.c1 != c1 || this.c2 != c2){
35632                     Ext.fly(this.elNode).replaceClass(c1, c2);
35633                     this.c1 = c1; this.c2 = c2;
35634                 }
35635             }else{
35636                 if(!this.wasLeaf){
35637                     Ext.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-collapsed");
35638                     delete this.c1;
35639                     delete this.c2;
35640                     this.wasLeaf = true;
35641                 }
35642             }
35643             var ecc = "x-tree-ec-icon "+cls;
35644             if(this.ecc != ecc){
35645                 this.ecNode.className = ecc;
35646                 this.ecc = ecc;
35647             }
35648         }
35649     },
35650
35651     
35652     onIdChange: function(id){
35653         if(this.rendered){
35654             this.elNode.setAttribute('ext:tree-node-id', id);
35655         }
35656     },
35657
35658     
35659     getChildIndent : function(){
35660         if(!this.childIndent){
35661             var buf = [],
35662                 p = this.node;
35663             while(p){
35664                 if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){
35665                     if(!p.isLast()) {
35666                         buf.unshift('<img alt="" src="'+this.emptyIcon+'" class="x-tree-elbow-line" />');
35667                     } else {
35668                         buf.unshift('<img alt="" src="'+this.emptyIcon+'" class="x-tree-icon" />');
35669                     }
35670                 }
35671                 p = p.parentNode;
35672             }
35673             this.childIndent = buf.join("");
35674         }
35675         return this.childIndent;
35676     },
35677
35678     
35679     renderIndent : function(){
35680         if(this.rendered){
35681             var indent = "",
35682                 p = this.node.parentNode;
35683             if(p){
35684                 indent = p.ui.getChildIndent();
35685             }
35686             if(this.indentMarkup != indent){ 
35687                 this.indentNode.innerHTML = indent;
35688                 this.indentMarkup = indent;
35689             }
35690             this.updateExpandIcon();
35691         }
35692     },
35693
35694     destroy : function(){
35695         if(this.elNode){
35696             Ext.dd.Registry.unregister(this.elNode.id);
35697         }
35698
35699         Ext.each(['textnode', 'anchor', 'checkbox', 'indentNode', 'ecNode', 'iconNode', 'elNode', 'ctNode', 'wrap', 'holder'], function(el){
35700             if(this[el]){
35701                 Ext.fly(this[el]).remove();
35702                 delete this[el];
35703             }
35704         }, this);
35705         delete this.node;
35706     }
35707 });
35708
35709
35710 Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
35711     
35712     render : function(){
35713         if(!this.rendered){
35714             var targetNode = this.node.ownerTree.innerCt.dom;
35715             this.node.expanded = true;
35716             targetNode.innerHTML = '<div class="x-tree-root-node"></div>';
35717             this.wrap = this.ctNode = targetNode.firstChild;
35718         }
35719     },
35720     collapse : Ext.emptyFn,
35721     expand : Ext.emptyFn
35722 });
35723 Ext.tree.TreeLoader = function(config){
35724     this.baseParams = {};
35725     Ext.apply(this, config);
35726
35727     this.addEvents(
35728         
35729         "beforeload",
35730         
35731         "load",
35732         
35733         "loadexception"
35734     );
35735     Ext.tree.TreeLoader.superclass.constructor.call(this);
35736     if(Ext.isString(this.paramOrder)){
35737         this.paramOrder = this.paramOrder.split(/[\s,|]/);
35738     }
35739 };
35740
35741 Ext.extend(Ext.tree.TreeLoader, Ext.util.Observable, {
35742     
35743     
35744     
35745     
35746     
35747     
35748     
35749     uiProviders : {},
35750
35751     
35752     clearOnLoad : true,
35753
35754     
35755     paramOrder: undefined,
35756
35757     
35758     paramsAsHash: false,
35759
35760     
35761     nodeParameter: 'node',
35762
35763     
35764     directFn : undefined,
35765
35766     
35767     load : function(node, callback, scope){
35768         if(this.clearOnLoad){
35769             while(node.firstChild){
35770                 node.removeChild(node.firstChild);
35771             }
35772         }
35773         if(this.doPreload(node)){ 
35774             this.runCallback(callback, scope || node, [node]);
35775         }else if(this.directFn || this.dataUrl || this.url){
35776             this.requestData(node, callback, scope || node);
35777         }
35778     },
35779
35780     doPreload : function(node){
35781         if(node.attributes.children){
35782             if(node.childNodes.length < 1){ 
35783                 var cs = node.attributes.children;
35784                 node.beginUpdate();
35785                 for(var i = 0, len = cs.length; i < len; i++){
35786                     var cn = node.appendChild(this.createNode(cs[i]));
35787                     if(this.preloadChildren){
35788                         this.doPreload(cn);
35789                     }
35790                 }
35791                 node.endUpdate();
35792             }
35793             return true;
35794         }
35795         return false;
35796     },
35797
35798     getParams: function(node){
35799         var bp = Ext.apply({}, this.baseParams),
35800             np = this.nodeParameter,
35801             po = this.paramOrder;
35802
35803         np && (bp[ np ] = node.id);
35804
35805         if(this.directFn){
35806             var buf = [node.id];
35807             if(po){
35808                 
35809                 if(np && po.indexOf(np) > -1){
35810                     buf = [];
35811                 }
35812
35813                 for(var i = 0, len = po.length; i < len; i++){
35814                     buf.push(bp[ po[i] ]);
35815                 }
35816             }else if(this.paramsAsHash){
35817                 buf = [bp];
35818             }
35819             return buf;
35820         }else{
35821             return bp;
35822         }
35823     },
35824
35825     requestData : function(node, callback, scope){
35826         if(this.fireEvent("beforeload", this, node, callback) !== false){
35827             if(this.directFn){
35828                 var args = this.getParams(node);
35829                 args.push(this.processDirectResponse.createDelegate(this, [{callback: callback, node: node, scope: scope}], true));
35830                 this.directFn.apply(window, args);
35831             }else{
35832                 this.transId = Ext.Ajax.request({
35833                     method:this.requestMethod,
35834                     url: this.dataUrl||this.url,
35835                     success: this.handleResponse,
35836                     failure: this.handleFailure,
35837                     scope: this,
35838                     argument: {callback: callback, node: node, scope: scope},
35839                     params: this.getParams(node)
35840                 });
35841             }
35842         }else{
35843             
35844             
35845             this.runCallback(callback, scope || node, []);
35846         }
35847     },
35848
35849     processDirectResponse: function(result, response, args){
35850         if(response.status){
35851             this.handleResponse({
35852                 responseData: Ext.isArray(result) ? result : null,
35853                 responseText: result,
35854                 argument: args
35855             });
35856         }else{
35857             this.handleFailure({
35858                 argument: args
35859             });
35860         }
35861     },
35862
35863     
35864     runCallback: function(cb, scope, args){
35865         if(Ext.isFunction(cb)){
35866             cb.apply(scope, args);
35867         }
35868     },
35869
35870     isLoading : function(){
35871         return !!this.transId;
35872     },
35873
35874     abort : function(){
35875         if(this.isLoading()){
35876             Ext.Ajax.abort(this.transId);
35877         }
35878     },
35879
35880     
35881     createNode : function(attr){
35882         
35883         if(this.baseAttrs){
35884             Ext.applyIf(attr, this.baseAttrs);
35885         }
35886         if(this.applyLoader !== false && !attr.loader){
35887             attr.loader = this;
35888         }
35889         if(Ext.isString(attr.uiProvider)){
35890            attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);
35891         }
35892         if(attr.nodeType){
35893             return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);
35894         }else{
35895             return attr.leaf ?
35896                         new Ext.tree.TreeNode(attr) :
35897                         new Ext.tree.AsyncTreeNode(attr);
35898         }
35899     },
35900
35901     processResponse : function(response, node, callback, scope){
35902         var json = response.responseText;
35903         try {
35904             var o = response.responseData || Ext.decode(json);
35905             node.beginUpdate();
35906             for(var i = 0, len = o.length; i < len; i++){
35907                 var n = this.createNode(o[i]);
35908                 if(n){
35909                     node.appendChild(n);
35910                 }
35911             }
35912             node.endUpdate();
35913             this.runCallback(callback, scope || node, [node]);
35914         }catch(e){
35915             this.handleFailure(response);
35916         }
35917     },
35918
35919     handleResponse : function(response){
35920         this.transId = false;
35921         var a = response.argument;
35922         this.processResponse(response, a.node, a.callback, a.scope);
35923         this.fireEvent("load", this, a.node, response);
35924     },
35925
35926     handleFailure : function(response){
35927         this.transId = false;
35928         var a = response.argument;
35929         this.fireEvent("loadexception", this, a.node, response);
35930         this.runCallback(a.callback, a.scope || a.node, [a.node]);
35931     },
35932
35933     destroy : function(){
35934         this.abort();
35935         this.purgeListeners();
35936     }
35937 });
35938 Ext.tree.TreeFilter = function(tree, config){
35939     this.tree = tree;
35940     this.filtered = {};
35941     Ext.apply(this, config);
35942 };
35943
35944 Ext.tree.TreeFilter.prototype = {
35945     clearBlank:false,
35946     reverse:false,
35947     autoClear:false,
35948     remove:false,
35949
35950      
35951     filter : function(value, attr, startNode){
35952         attr = attr || "text";
35953         var f;
35954         if(typeof value == "string"){
35955             var vlen = value.length;
35956             
35957             if(vlen == 0 && this.clearBlank){
35958                 this.clear();
35959                 return;
35960             }
35961             value = value.toLowerCase();
35962             f = function(n){
35963                 return n.attributes[attr].substr(0, vlen).toLowerCase() == value;
35964             };
35965         }else if(value.exec){ 
35966             f = function(n){
35967                 return value.test(n.attributes[attr]);
35968             };
35969         }else{
35970             throw 'Illegal filter type, must be string or regex';
35971         }
35972         this.filterBy(f, null, startNode);
35973         },
35974
35975     
35976     filterBy : function(fn, scope, startNode){
35977         startNode = startNode || this.tree.root;
35978         if(this.autoClear){
35979             this.clear();
35980         }
35981         var af = this.filtered, rv = this.reverse;
35982         var f = function(n){
35983             if(n == startNode){
35984                 return true;
35985             }
35986             if(af[n.id]){
35987                 return false;
35988             }
35989             var m = fn.call(scope || n, n);
35990             if(!m || rv){
35991                 af[n.id] = n;
35992                 n.ui.hide();
35993                 return false;
35994             }
35995             return true;
35996         };
35997         startNode.cascade(f);
35998         if(this.remove){
35999            for(var id in af){
36000                if(typeof id != "function"){
36001                    var n = af[id];
36002                    if(n && n.parentNode){
36003                        n.parentNode.removeChild(n);
36004                    }
36005                }
36006            }
36007         }
36008     },
36009
36010     
36011     clear : function(){
36012         var t = this.tree;
36013         var af = this.filtered;
36014         for(var id in af){
36015             if(typeof id != "function"){
36016                 var n = af[id];
36017                 if(n){
36018                     n.ui.show();
36019                 }
36020             }
36021         }
36022         this.filtered = {};
36023     }
36024 };
36025
36026 Ext.tree.TreeSorter = Ext.extend(Object, {
36027     
36028     constructor: function(tree, config){
36029         
36030     
36031     
36032     
36033     
36034     
36035
36036     Ext.apply(this, config);
36037     tree.on({
36038         scope: this,
36039         beforechildrenrendered: this.doSort,
36040         append: this.updateSort,
36041         insert: this.updateSort,
36042         textchange: this.updateSortParent
36043     });
36044
36045     var desc = this.dir && this.dir.toLowerCase() == 'desc',
36046         prop = this.property || 'text';
36047         sortType = this.sortType;
36048         folderSort = this.folderSort;
36049         caseSensitive = this.caseSensitive === true;
36050         leafAttr = this.leafAttr || 'leaf';
36051
36052     if(Ext.isString(sortType)){
36053         sortType = Ext.data.SortTypes[sortType];
36054     }
36055     this.sortFn = function(n1, n2){
36056         var attr1 = n1.attributes,
36057             attr2 = n2.attributes;
36058             
36059         if(folderSort){
36060             if(attr1[leafAttr] && !attr2[leafAttr]){
36061                 return 1;
36062             }
36063             if(!attr1[leafAttr] && attr2[leafAttr]){
36064                 return -1;
36065             }
36066         }
36067         var prop1 = attr1[prop],
36068             prop2 = attr2[prop],
36069             v1 = sortType ? sortType(prop1) : (caseSensitive ? prop1 : prop1.toUpperCase());
36070             v2 = sortType ? sortType(prop2) : (caseSensitive ? prop2 : prop2.toUpperCase());
36071             
36072         if(v1 < v2){
36073             return desc ? 1 : -1;
36074         }else if(v1 > v2){
36075             return desc ? -1 : 1;
36076         }
36077         return 0;
36078     };
36079     },
36080     
36081     doSort : function(node){
36082         node.sort(this.sortFn);
36083     },
36084
36085     updateSort : function(tree, node){
36086         if(node.childrenRendered){
36087             this.doSort.defer(1, this, [node]);
36088         }
36089     },
36090
36091     updateSortParent : function(node){
36092         var p = node.parentNode;
36093         if(p && p.childrenRendered){
36094             this.doSort.defer(1, this, [p]);
36095         }
36096     }    
36097 });
36098 if(Ext.dd.DropZone){
36099     
36100 Ext.tree.TreeDropZone = function(tree, config){
36101     
36102     this.allowParentInsert = config.allowParentInsert || false;
36103     
36104     this.allowContainerDrop = config.allowContainerDrop || false;
36105     
36106     this.appendOnly = config.appendOnly || false;
36107
36108     Ext.tree.TreeDropZone.superclass.constructor.call(this, tree.getTreeEl(), config);
36109     
36110     this.tree = tree;
36111     
36112     this.dragOverData = {};
36113     
36114     this.lastInsertClass = "x-tree-no-status";
36115 };
36116
36117 Ext.extend(Ext.tree.TreeDropZone, Ext.dd.DropZone, {
36118     
36119     ddGroup : "TreeDD",
36120
36121     
36122     expandDelay : 1000,
36123
36124     
36125     expandNode : function(node){
36126         if(node.hasChildNodes() && !node.isExpanded()){
36127             node.expand(false, null, this.triggerCacheRefresh.createDelegate(this));
36128         }
36129     },
36130
36131     
36132     queueExpand : function(node){
36133         this.expandProcId = this.expandNode.defer(this.expandDelay, this, [node]);
36134     },
36135
36136     
36137     cancelExpand : function(){
36138         if(this.expandProcId){
36139             clearTimeout(this.expandProcId);
36140             this.expandProcId = false;
36141         }
36142     },
36143
36144     
36145     isValidDropPoint : function(n, pt, dd, e, data){
36146         if(!n || !data){ return false; }
36147         var targetNode = n.node;
36148         var dropNode = data.node;
36149         
36150         if(!(targetNode && targetNode.isTarget && pt)){
36151             return false;
36152         }
36153         if(pt == "append" && targetNode.allowChildren === false){
36154             return false;
36155         }
36156         if((pt == "above" || pt == "below") && (targetNode.parentNode && targetNode.parentNode.allowChildren === false)){
36157             return false;
36158         }
36159         if(dropNode && (targetNode == dropNode || dropNode.contains(targetNode))){
36160             return false;
36161         }
36162         
36163         var overEvent = this.dragOverData;
36164         overEvent.tree = this.tree;
36165         overEvent.target = targetNode;
36166         overEvent.data = data;
36167         overEvent.point = pt;
36168         overEvent.source = dd;
36169         overEvent.rawEvent = e;
36170         overEvent.dropNode = dropNode;
36171         overEvent.cancel = false;  
36172         var result = this.tree.fireEvent("nodedragover", overEvent);
36173         return overEvent.cancel === false && result !== false;
36174     },
36175
36176     
36177     getDropPoint : function(e, n, dd){
36178         var tn = n.node;
36179         if(tn.isRoot){
36180             return tn.allowChildren !== false ? "append" : false; 
36181         }
36182         var dragEl = n.ddel;
36183         var t = Ext.lib.Dom.getY(dragEl), b = t + dragEl.offsetHeight;
36184         var y = Ext.lib.Event.getPageY(e);
36185         var noAppend = tn.allowChildren === false || tn.isLeaf();
36186         if(this.appendOnly || tn.parentNode.allowChildren === false){
36187             return noAppend ? false : "append";
36188         }
36189         var noBelow = false;
36190         if(!this.allowParentInsert){
36191             noBelow = tn.hasChildNodes() && tn.isExpanded();
36192         }
36193         var q = (b - t) / (noAppend ? 2 : 3);
36194         if(y >= t && y < (t + q)){
36195             return "above";
36196         }else if(!noBelow && (noAppend || y >= b-q && y <= b)){
36197             return "below";
36198         }else{
36199             return "append";
36200         }
36201     },
36202
36203     
36204     onNodeEnter : function(n, dd, e, data){
36205         this.cancelExpand();
36206     },
36207     
36208     onContainerOver : function(dd, e, data) {
36209         if (this.allowContainerDrop && this.isValidDropPoint({ ddel: this.tree.getRootNode().ui.elNode, node: this.tree.getRootNode() }, "append", dd, e, data)) {
36210             return this.dropAllowed;
36211         }
36212         return this.dropNotAllowed;
36213     },
36214
36215     
36216     onNodeOver : function(n, dd, e, data){
36217         var pt = this.getDropPoint(e, n, dd);
36218         var node = n.node;
36219         
36220         
36221         if(!this.expandProcId && pt == "append" && node.hasChildNodes() && !n.node.isExpanded()){
36222             this.queueExpand(node);
36223         }else if(pt != "append"){
36224             this.cancelExpand();
36225         }
36226         
36227         
36228         var returnCls = this.dropNotAllowed;
36229         if(this.isValidDropPoint(n, pt, dd, e, data)){
36230            if(pt){
36231                var el = n.ddel;
36232                var cls;
36233                if(pt == "above"){
36234                    returnCls = n.node.isFirst() ? "x-tree-drop-ok-above" : "x-tree-drop-ok-between";
36235                    cls = "x-tree-drag-insert-above";
36236                }else if(pt == "below"){
36237                    returnCls = n.node.isLast() ? "x-tree-drop-ok-below" : "x-tree-drop-ok-between";
36238                    cls = "x-tree-drag-insert-below";
36239                }else{
36240                    returnCls = "x-tree-drop-ok-append";
36241                    cls = "x-tree-drag-append";
36242                }
36243                if(this.lastInsertClass != cls){
36244                    Ext.fly(el).replaceClass(this.lastInsertClass, cls);
36245                    this.lastInsertClass = cls;
36246                }
36247            }
36248        }
36249        return returnCls;
36250     },
36251
36252     
36253     onNodeOut : function(n, dd, e, data){
36254         this.cancelExpand();
36255         this.removeDropIndicators(n);
36256     },
36257
36258     
36259     onNodeDrop : function(n, dd, e, data){
36260         var point = this.getDropPoint(e, n, dd);
36261         var targetNode = n.node;
36262         targetNode.ui.startDrop();
36263         if(!this.isValidDropPoint(n, point, dd, e, data)){
36264             targetNode.ui.endDrop();
36265             return false;
36266         }
36267         
36268         var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, point, e) : null);
36269         return this.processDrop(targetNode, data, point, dd, e, dropNode);
36270     },
36271     
36272     onContainerDrop : function(dd, e, data){
36273         if (this.allowContainerDrop && this.isValidDropPoint({ ddel: this.tree.getRootNode().ui.elNode, node: this.tree.getRootNode() }, "append", dd, e, data)) {
36274             var targetNode = this.tree.getRootNode();       
36275             targetNode.ui.startDrop();
36276             var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, 'append', e) : null);
36277             return this.processDrop(targetNode, data, 'append', dd, e, dropNode);
36278         }
36279         return false;
36280     },
36281     
36282     
36283     processDrop: function(target, data, point, dd, e, dropNode){
36284         var dropEvent = {
36285             tree : this.tree,
36286             target: target,
36287             data: data,
36288             point: point,
36289             source: dd,
36290             rawEvent: e,
36291             dropNode: dropNode,
36292             cancel: !dropNode,
36293             dropStatus: false
36294         };
36295         var retval = this.tree.fireEvent("beforenodedrop", dropEvent);
36296         if(retval === false || dropEvent.cancel === true || !dropEvent.dropNode){
36297             target.ui.endDrop();
36298             return dropEvent.dropStatus;
36299         }
36300     
36301         target = dropEvent.target;
36302         if(point == 'append' && !target.isExpanded()){
36303             target.expand(false, null, function(){
36304                 this.completeDrop(dropEvent);
36305             }.createDelegate(this));
36306         }else{
36307             this.completeDrop(dropEvent);
36308         }
36309         return true;
36310     },
36311
36312     
36313     completeDrop : function(de){
36314         var ns = de.dropNode, p = de.point, t = de.target;
36315         if(!Ext.isArray(ns)){
36316             ns = [ns];
36317         }
36318         var n;
36319         for(var i = 0, len = ns.length; i < len; i++){
36320             n = ns[i];
36321             if(p == "above"){
36322                 t.parentNode.insertBefore(n, t);
36323             }else if(p == "below"){
36324                 t.parentNode.insertBefore(n, t.nextSibling);
36325             }else{
36326                 t.appendChild(n);
36327             }
36328         }
36329         n.ui.focus();
36330         if(Ext.enableFx && this.tree.hlDrop){
36331             n.ui.highlight();
36332         }
36333         t.ui.endDrop();
36334         this.tree.fireEvent("nodedrop", de);
36335     },
36336
36337     
36338     afterNodeMoved : function(dd, data, e, targetNode, dropNode){
36339         if(Ext.enableFx && this.tree.hlDrop){
36340             dropNode.ui.focus();
36341             dropNode.ui.highlight();
36342         }
36343         this.tree.fireEvent("nodedrop", this.tree, targetNode, data, dd, e);
36344     },
36345
36346     
36347     getTree : function(){
36348         return this.tree;
36349     },
36350
36351     
36352     removeDropIndicators : function(n){
36353         if(n && n.ddel){
36354             var el = n.ddel;
36355             Ext.fly(el).removeClass([
36356                     "x-tree-drag-insert-above",
36357                     "x-tree-drag-insert-below",
36358                     "x-tree-drag-append"]);
36359             this.lastInsertClass = "_noclass";
36360         }
36361     },
36362
36363     
36364     beforeDragDrop : function(target, e, id){
36365         this.cancelExpand();
36366         return true;
36367     },
36368
36369     
36370     afterRepair : function(data){
36371         if(data && Ext.enableFx){
36372             data.node.ui.highlight();
36373         }
36374         this.hideProxy();
36375     }    
36376 });
36377
36378 }
36379 if(Ext.dd.DragZone){
36380 Ext.tree.TreeDragZone = function(tree, config){
36381     Ext.tree.TreeDragZone.superclass.constructor.call(this, tree.innerCt, config);
36382     
36383     this.tree = tree;
36384 };
36385
36386 Ext.extend(Ext.tree.TreeDragZone, Ext.dd.DragZone, {
36387     
36388     ddGroup : "TreeDD",
36389
36390     
36391     onBeforeDrag : function(data, e){
36392         var n = data.node;
36393         return n && n.draggable && !n.disabled;
36394     },
36395
36396     
36397     onInitDrag : function(e){
36398         var data = this.dragData;
36399         this.tree.getSelectionModel().select(data.node);
36400         this.tree.eventModel.disable();
36401         this.proxy.update("");
36402         data.node.ui.appendDDGhost(this.proxy.ghost.dom);
36403         this.tree.fireEvent("startdrag", this.tree, data.node, e);
36404     },
36405
36406     
36407     getRepairXY : function(e, data){
36408         return data.node.ui.getDDRepairXY();
36409     },
36410
36411     
36412     onEndDrag : function(data, e){
36413         this.tree.eventModel.enable.defer(100, this.tree.eventModel);
36414         this.tree.fireEvent("enddrag", this.tree, data.node, e);
36415     },
36416
36417     
36418     onValidDrop : function(dd, e, id){
36419         this.tree.fireEvent("dragdrop", this.tree, this.dragData.node, dd, e);
36420         this.hideProxy();
36421     },
36422
36423     
36424     beforeInvalidDrop : function(e, id){
36425         
36426         var sm = this.tree.getSelectionModel();
36427         sm.clearSelections();
36428         sm.select(this.dragData.node);
36429     },
36430     
36431     
36432     afterRepair : function(){
36433         if (Ext.enableFx && this.tree.hlDrop) {
36434             Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
36435         }
36436         this.dragging = false;
36437     }
36438 });
36439 }
36440 Ext.tree.TreeEditor = function(tree, fc, config){
36441     fc = fc || {};
36442     var field = fc.events ? fc : new Ext.form.TextField(fc);
36443     
36444     Ext.tree.TreeEditor.superclass.constructor.call(this, field, config);
36445
36446     this.tree = tree;
36447
36448     if(!tree.rendered){
36449         tree.on('render', this.initEditor, this);
36450     }else{
36451         this.initEditor(tree);
36452     }
36453 };
36454
36455 Ext.extend(Ext.tree.TreeEditor, Ext.Editor, {
36456     
36457     alignment: "l-l",
36458     
36459     autoSize: false,
36460     
36461     hideEl : false,
36462     
36463     cls: "x-small-editor x-tree-editor",
36464     
36465     shim:false,
36466     
36467     shadow:"frame",
36468     
36469     maxWidth: 250,
36470     
36471     editDelay : 350,
36472
36473     initEditor : function(tree){
36474         tree.on({
36475             scope      : this,
36476             beforeclick: this.beforeNodeClick,
36477             dblclick   : this.onNodeDblClick
36478         });
36479         
36480         this.on({
36481             scope          : this,
36482             complete       : this.updateNode,
36483             beforestartedit: this.fitToTree,
36484             specialkey     : this.onSpecialKey
36485         });
36486         
36487         this.on('startedit', this.bindScroll, this, {delay:10});
36488     },
36489
36490     
36491     fitToTree : function(ed, el){
36492         var td = this.tree.getTreeEl().dom, nd = el.dom;
36493         if(td.scrollLeft >  nd.offsetLeft){ 
36494             td.scrollLeft = nd.offsetLeft;
36495         }
36496         var w = Math.min(
36497                 this.maxWidth,
36498                 (td.clientWidth > 20 ? td.clientWidth : td.offsetWidth) - Math.max(0, nd.offsetLeft-td.scrollLeft) - 5);
36499         this.setSize(w, '');
36500     },
36501
36502     
36503     triggerEdit : function(node, defer){
36504         this.completeEdit();
36505                 if(node.attributes.editable !== false){
36506            
36507                         this.editNode = node;
36508             if(this.tree.autoScroll){
36509                 Ext.fly(node.ui.getEl()).scrollIntoView(this.tree.body);
36510             }
36511             var value = node.text || '';
36512             if (!Ext.isGecko && Ext.isEmpty(node.text)){
36513                 node.setText('&#160;');
36514             }
36515             this.autoEditTimer = this.startEdit.defer(this.editDelay, this, [node.ui.textNode, value]);
36516             return false;
36517         }
36518     },
36519
36520     
36521     bindScroll : function(){
36522         this.tree.getTreeEl().on('scroll', this.cancelEdit, this);
36523     },
36524
36525     
36526     beforeNodeClick : function(node, e){
36527         clearTimeout(this.autoEditTimer);
36528         if(this.tree.getSelectionModel().isSelected(node)){
36529             e.stopEvent();
36530             return this.triggerEdit(node);
36531         }
36532     },
36533
36534     onNodeDblClick : function(node, e){
36535         clearTimeout(this.autoEditTimer);
36536     },
36537
36538     
36539     updateNode : function(ed, value){
36540         this.tree.getTreeEl().un('scroll', this.cancelEdit, this);
36541         this.editNode.setText(value);
36542     },
36543
36544     
36545     onHide : function(){
36546         Ext.tree.TreeEditor.superclass.onHide.call(this);
36547         if(this.editNode){
36548             this.editNode.ui.focus.defer(50, this.editNode.ui);
36549         }
36550     },
36551
36552     
36553     onSpecialKey : function(field, e){
36554         var k = e.getKey();
36555         if(k == e.ESC){
36556             e.stopEvent();
36557             this.cancelEdit();
36558         }else if(k == e.ENTER && !e.hasModifier()){
36559             e.stopEvent();
36560             this.completeEdit();
36561         }
36562     },
36563     
36564     onDestroy : function(){
36565         clearTimeout(this.autoEditTimer);
36566         Ext.tree.TreeEditor.superclass.onDestroy.call(this);
36567         var tree = this.tree;
36568         tree.un('beforeclick', this.beforeNodeClick, this);
36569         tree.un('dblclick', this.onNodeDblClick, this);
36570     }
36571 });
36572
36573 var swfobject = function() {
36574     
36575     var UNDEF = "undefined",
36576         OBJECT = "object",
36577         SHOCKWAVE_FLASH = "Shockwave Flash",
36578         SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
36579         FLASH_MIME_TYPE = "application/x-shockwave-flash",
36580         EXPRESS_INSTALL_ID = "SWFObjectExprInst",
36581         ON_READY_STATE_CHANGE = "onreadystatechange",
36582         
36583         win = window,
36584         doc = document,
36585         nav = navigator,
36586         
36587         plugin = false,
36588         domLoadFnArr = [main],
36589         regObjArr = [],
36590         objIdArr = [],
36591         listenersArr = [],
36592         storedAltContent,
36593         storedAltContentId,
36594         storedCallbackFn,
36595         storedCallbackObj,
36596         isDomLoaded = false,
36597         isExpressInstallActive = false,
36598         dynamicStylesheet,
36599         dynamicStylesheetMedia,
36600         autoHideShow = true,
36601     
36602       
36603     ua = function() {
36604         var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
36605             u = nav.userAgent.toLowerCase(),
36606             p = nav.platform.toLowerCase(),
36607             windows = p ? (/win/).test(p) : /win/.test(u),
36608             mac = p ? (/mac/).test(p) : /mac/.test(u),
36609             webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, 
36610             ie = !+"\v1", 
36611             playerVersion = [0,0,0],
36612             d = null;
36613         if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
36614             d = nav.plugins[SHOCKWAVE_FLASH].description;
36615             if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { 
36616                 plugin = true;
36617                 ie = false; 
36618                 d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
36619                 playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
36620                 playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
36621                 playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
36622             }
36623         }
36624         else if (typeof win.ActiveXObject != UNDEF) {
36625             try {
36626                 var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
36627                 if (a) { 
36628                     d = a.GetVariable("$version");
36629                     if (d) {
36630                         ie = true; 
36631                         d = d.split(" ")[1].split(",");
36632                         playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
36633                     }
36634                 }
36635             }
36636             catch(e) {}
36637         }
36638         return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac };
36639     }(),
36640     
36641      
36642     onDomLoad = function() {
36643         if (!ua.w3) { return; }
36644         if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { 
36645             callDomLoadFunctions();
36646         }
36647         if (!isDomLoaded) {
36648             if (typeof doc.addEventListener != UNDEF) {
36649                 doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false);
36650             }       
36651             if (ua.ie && ua.win) {
36652                 doc.attachEvent(ON_READY_STATE_CHANGE, function() {
36653                     if (doc.readyState == "complete") {
36654                         doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee);
36655                         callDomLoadFunctions();
36656                     }
36657                 });
36658                 if (win == top) { 
36659                     (function(){
36660                         if (isDomLoaded) { return; }
36661                         try {
36662                             doc.documentElement.doScroll("left");
36663                         }
36664                         catch(e) {
36665                             setTimeout(arguments.callee, 0);
36666                             return;
36667                         }
36668                         callDomLoadFunctions();
36669                     })();
36670                 }
36671             }
36672             if (ua.wk) {
36673                 (function(){
36674                     if (isDomLoaded) { return; }
36675                     if (!(/loaded|complete/).test(doc.readyState)) {
36676                         setTimeout(arguments.callee, 0);
36677                         return;
36678                     }
36679                     callDomLoadFunctions();
36680                 })();
36681             }
36682             addLoadEvent(callDomLoadFunctions);
36683         }
36684     }();
36685     
36686     function callDomLoadFunctions() {
36687         if (isDomLoaded) { return; }
36688         try { 
36689             var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span"));
36690             t.parentNode.removeChild(t);
36691         }
36692         catch (e) { return; }
36693         isDomLoaded = true;
36694         var dl = domLoadFnArr.length;
36695         for (var i = 0; i < dl; i++) {
36696             domLoadFnArr[i]();
36697         }
36698     }
36699     
36700     function addDomLoadEvent(fn) {
36701         if (isDomLoaded) {
36702             fn();
36703         }
36704         else { 
36705             domLoadFnArr[domLoadFnArr.length] = fn; 
36706         }
36707     }
36708     
36709     
36710     function addLoadEvent(fn) {
36711         if (typeof win.addEventListener != UNDEF) {
36712             win.addEventListener("load", fn, false);
36713         }
36714         else if (typeof doc.addEventListener != UNDEF) {
36715             doc.addEventListener("load", fn, false);
36716         }
36717         else if (typeof win.attachEvent != UNDEF) {
36718             addListener(win, "onload", fn);
36719         }
36720         else if (typeof win.onload == "function") {
36721             var fnOld = win.onload;
36722             win.onload = function() {
36723                 fnOld();
36724                 fn();
36725             };
36726         }
36727         else {
36728             win.onload = fn;
36729         }
36730     }
36731     
36732     
36733     function main() { 
36734         if (plugin) {
36735             testPlayerVersion();
36736         }
36737         else {
36738             matchVersions();
36739         }
36740     }
36741     
36742     
36743     function testPlayerVersion() {
36744         var b = doc.getElementsByTagName("body")[0];
36745         var o = createElement(OBJECT);
36746         o.setAttribute("type", FLASH_MIME_TYPE);
36747         var t = b.appendChild(o);
36748         if (t) {
36749             var counter = 0;
36750             (function(){
36751                 if (typeof t.GetVariable != UNDEF) {
36752                     var d = t.GetVariable("$version");
36753                     if (d) {
36754                         d = d.split(" ")[1].split(",");
36755                         ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
36756                     }
36757                 }
36758                 else if (counter < 10) {
36759                     counter++;
36760                     setTimeout(arguments.callee, 10);
36761                     return;
36762                 }
36763                 b.removeChild(o);
36764                 t = null;
36765                 matchVersions();
36766             })();
36767         }
36768         else {
36769             matchVersions();
36770         }
36771     }
36772     
36773     
36774     function matchVersions() {
36775         var rl = regObjArr.length;
36776         if (rl > 0) {
36777             for (var i = 0; i < rl; i++) { 
36778                 var id = regObjArr[i].id;
36779                 var cb = regObjArr[i].callbackFn;
36780                 var cbObj = {success:false, id:id};
36781                 if (ua.pv[0] > 0) {
36782                     var obj = getElementById(id);
36783                     if (obj) {
36784                         if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { 
36785                             setVisibility(id, true);
36786                             if (cb) {
36787                                 cbObj.success = true;
36788                                 cbObj.ref = getObjectById(id);
36789                                 cb(cbObj);
36790                             }
36791                         }
36792                         else if (regObjArr[i].expressInstall && canExpressInstall()) { 
36793                             var att = {};
36794                             att.data = regObjArr[i].expressInstall;
36795                             att.width = obj.getAttribute("width") || "0";
36796                             att.height = obj.getAttribute("height") || "0";
36797                             if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); }
36798                             if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); }
36799                             
36800                             var par = {};
36801                             var p = obj.getElementsByTagName("param");
36802                             var pl = p.length;
36803                             for (var j = 0; j < pl; j++) {
36804                                 if (p[j].getAttribute("name").toLowerCase() != "movie") {
36805                                     par[p[j].getAttribute("name")] = p[j].getAttribute("value");
36806                                 }
36807                             }
36808                             showExpressInstall(att, par, id, cb);
36809                         }
36810                         else { 
36811                             displayAltContent(obj);
36812                             if (cb) { cb(cbObj); }
36813                         }
36814                     }
36815                 }
36816                 else {  
36817                     setVisibility(id, true);
36818                     if (cb) {
36819                         var o = getObjectById(id); 
36820                         if (o && typeof o.SetVariable != UNDEF) { 
36821                             cbObj.success = true;
36822                             cbObj.ref = o;
36823                         }
36824                         cb(cbObj);
36825                     }
36826                 }
36827             }
36828         }
36829     }
36830     
36831     function getObjectById(objectIdStr) {
36832         var r = null;
36833         var o = getElementById(objectIdStr);
36834         if (o && o.nodeName == "OBJECT") {
36835             if (typeof o.SetVariable != UNDEF) {
36836                 r = o;
36837             }
36838             else {
36839                 var n = o.getElementsByTagName(OBJECT)[0];
36840                 if (n) {
36841                     r = n;
36842                 }
36843             }
36844         }
36845         return r;
36846     }
36847     
36848     
36849     function canExpressInstall() {
36850         return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312);
36851     }
36852     
36853     
36854     function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
36855         isExpressInstallActive = true;
36856         storedCallbackFn = callbackFn || null;
36857         storedCallbackObj = {success:false, id:replaceElemIdStr};
36858         var obj = getElementById(replaceElemIdStr);
36859         if (obj) {
36860             if (obj.nodeName == "OBJECT") { 
36861                 storedAltContent = abstractAltContent(obj);
36862                 storedAltContentId = null;
36863             }
36864             else { 
36865                 storedAltContent = obj;
36866                 storedAltContentId = replaceElemIdStr;
36867             }
36868             att.id = EXPRESS_INSTALL_ID;
36869             if (typeof att.width == UNDEF || (!(/%$/).test(att.width) && parseInt(att.width, 10) < 310)) {
36870                 att.width = "310";
36871             }
36872             
36873             if (typeof att.height == UNDEF || (!(/%$/).test(att.height) && parseInt(att.height, 10) < 137)) {
36874                 att.height = "137";
36875             }
36876             doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";
36877             var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn",
36878                 fv = "MMredirectURL=" + win.location.toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title;
36879             if (typeof par.flashvars != UNDEF) {
36880                 par.flashvars += "&" + fv;
36881             }
36882             else {
36883                 par.flashvars = fv;
36884             }
36885             
36886             
36887             if (ua.ie && ua.win && obj.readyState != 4) {
36888                 var newObj = createElement("div");
36889                 replaceElemIdStr += "SWFObjectNew";
36890                 newObj.setAttribute("id", replaceElemIdStr);
36891                 obj.parentNode.insertBefore(newObj, obj); 
36892                 obj.style.display = "none";
36893                 (function(){
36894                     if (obj.readyState == 4) {
36895                         obj.parentNode.removeChild(obj);
36896                     }
36897                     else {
36898                         setTimeout(arguments.callee, 10);
36899                     }
36900                 })();
36901             }
36902             createSWF(att, par, replaceElemIdStr);
36903         }
36904     }
36905     
36906     
36907     function displayAltContent(obj) {
36908         if (ua.ie && ua.win && obj.readyState != 4) {
36909             
36910             
36911             var el = createElement("div");
36912             obj.parentNode.insertBefore(el, obj); 
36913             el.parentNode.replaceChild(abstractAltContent(obj), el);
36914             obj.style.display = "none";
36915             (function(){
36916                 if (obj.readyState == 4) {
36917                     obj.parentNode.removeChild(obj);
36918                 }
36919                 else {
36920                     setTimeout(arguments.callee, 10);
36921                 }
36922             })();
36923         }
36924         else {
36925             obj.parentNode.replaceChild(abstractAltContent(obj), obj);
36926         }
36927     } 
36928
36929     function abstractAltContent(obj) {
36930         var ac = createElement("div");
36931         if (ua.win && ua.ie) {
36932             ac.innerHTML = obj.innerHTML;
36933         }
36934         else {
36935             var nestedObj = obj.getElementsByTagName(OBJECT)[0];
36936             if (nestedObj) {
36937                 var c = nestedObj.childNodes;
36938                 if (c) {
36939                     var cl = c.length;
36940                     for (var i = 0; i < cl; i++) {
36941                         if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {
36942                             ac.appendChild(c[i].cloneNode(true));
36943                         }
36944                     }
36945                 }
36946             }
36947         }
36948         return ac;
36949     }
36950     
36951     
36952     function createSWF(attObj, parObj, id) {
36953         var r, el = getElementById(id);
36954         if (ua.wk && ua.wk < 312) { return r; }
36955         if (el) {
36956             if (typeof attObj.id == UNDEF) { 
36957                 attObj.id = id;
36958             }
36959             if (ua.ie && ua.win) { 
36960                 var att = "";
36961                 for (var i in attObj) {
36962                     if (attObj[i] != Object.prototype[i]) { 
36963                         if (i.toLowerCase() == "data") {
36964                             parObj.movie = attObj[i];
36965                         }
36966                         else if (i.toLowerCase() == "styleclass") { 
36967                             att += ' class="' + attObj[i] + '"';
36968                         }
36969                         else if (i.toLowerCase() != "classid") {
36970                             att += ' ' + i + '="' + attObj[i] + '"';
36971                         }
36972                     }
36973                 }
36974                 var par = "";
36975                 for (var j in parObj) {
36976                     if (parObj[j] != Object.prototype[j]) { 
36977                         par += '<param name="' + j + '" value="' + parObj[j] + '" />';
36978                     }
36979                 }
36980                 el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
36981                 objIdArr[objIdArr.length] = attObj.id; 
36982                 r = getElementById(attObj.id);  
36983             }
36984             else { 
36985                 var o = createElement(OBJECT);
36986                 o.setAttribute("type", FLASH_MIME_TYPE);
36987                 for (var m in attObj) {
36988                     if (attObj[m] != Object.prototype[m]) { 
36989                         if (m.toLowerCase() == "styleclass") { 
36990                             o.setAttribute("class", attObj[m]);
36991                         }
36992                         else if (m.toLowerCase() != "classid") { 
36993                             o.setAttribute(m, attObj[m]);
36994                         }
36995                     }
36996                 }
36997                 for (var n in parObj) {
36998                     if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { 
36999                         createObjParam(o, n, parObj[n]);
37000                     }
37001                 }
37002                 el.parentNode.replaceChild(o, el);
37003                 r = o;
37004             }
37005         }
37006         return r;
37007     }
37008     
37009     function createObjParam(el, pName, pValue) {
37010         var p = createElement("param");
37011         p.setAttribute("name", pName);  
37012         p.setAttribute("value", pValue);
37013         el.appendChild(p);
37014     }
37015     
37016     
37017     function removeSWF(id) {
37018         var obj = getElementById(id);
37019         if (obj && obj.nodeName == "OBJECT") {
37020             if (ua.ie && ua.win) {
37021                 obj.style.display = "none";
37022                 (function(){
37023                     if (obj.readyState == 4) {
37024                         removeObjectInIE(id);
37025                     }
37026                     else {
37027                         setTimeout(arguments.callee, 10);
37028                     }
37029                 })();
37030             }
37031             else {
37032                 obj.parentNode.removeChild(obj);
37033             }
37034         }
37035     }
37036     
37037     function removeObjectInIE(id) {
37038         var obj = getElementById(id);
37039         if (obj) {
37040             for (var i in obj) {
37041                 if (typeof obj[i] == "function") {
37042                     obj[i] = null;
37043                 }
37044             }
37045             obj.parentNode.removeChild(obj);
37046         }
37047     }
37048     
37049     
37050     function getElementById(id) {
37051         var el = null;
37052         try {
37053             el = doc.getElementById(id);
37054         }
37055         catch (e) {}
37056         return el;
37057     }
37058     
37059     function createElement(el) {
37060         return doc.createElement(el);
37061     }
37062     
37063       
37064     function addListener(target, eventType, fn) {
37065         target.attachEvent(eventType, fn);
37066         listenersArr[listenersArr.length] = [target, eventType, fn];
37067     }
37068     
37069     
37070     function hasPlayerVersion(rv) {
37071         var pv = ua.pv, v = rv.split(".");
37072         v[0] = parseInt(v[0], 10);
37073         v[1] = parseInt(v[1], 10) || 0; 
37074         v[2] = parseInt(v[2], 10) || 0;
37075         return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
37076     }
37077     
37078       
37079     function createCSS(sel, decl, media, newStyle) {
37080         if (ua.ie && ua.mac) { return; }
37081         var h = doc.getElementsByTagName("head")[0];
37082         if (!h) { return; } 
37083         var m = (media && typeof media == "string") ? media : "screen";
37084         if (newStyle) {
37085             dynamicStylesheet = null;
37086             dynamicStylesheetMedia = null;
37087         }
37088         if (!dynamicStylesheet || dynamicStylesheetMedia != m) { 
37089             
37090             var s = createElement("style");
37091             s.setAttribute("type", "text/css");
37092             s.setAttribute("media", m);
37093             dynamicStylesheet = h.appendChild(s);
37094             if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) {
37095                 dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1];
37096             }
37097             dynamicStylesheetMedia = m;
37098         }
37099         
37100         if (ua.ie && ua.win) {
37101             if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) {
37102                 dynamicStylesheet.addRule(sel, decl);
37103             }
37104         }
37105         else {
37106             if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) {
37107                 dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}"));
37108             }
37109         }
37110     }
37111     
37112     function setVisibility(id, isVisible) {
37113         if (!autoHideShow) { return; }
37114         var v = isVisible ? "visible" : "hidden";
37115         if (isDomLoaded && getElementById(id)) {
37116             getElementById(id).style.visibility = v;
37117         }
37118         else {
37119             createCSS("#" + id, "visibility:" + v);
37120         }
37121     }
37122
37123     
37124     function urlEncodeIfNecessary(s) {
37125         var regex = /[\\\"<>\.;]/;
37126         var hasBadChars = regex.exec(s) != null;
37127         return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s;
37128     }
37129     
37130     
37131     var cleanup = function() {
37132         if (ua.ie && ua.win) {
37133             window.attachEvent("onunload", function() {
37134                 
37135                 var ll = listenersArr.length;
37136                 for (var i = 0; i < ll; i++) {
37137                     listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
37138                 }
37139                 
37140                 var il = objIdArr.length;
37141                 for (var j = 0; j < il; j++) {
37142                     removeSWF(objIdArr[j]);
37143                 }
37144                 
37145                 for (var k in ua) {
37146                     ua[k] = null;
37147                 }
37148                 ua = null;
37149                 for (var l in swfobject) {
37150                     swfobject[l] = null;
37151                 }
37152                 swfobject = null;
37153             });
37154         }
37155     }();
37156     
37157     return {
37158          
37159         registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) {
37160             if (ua.w3 && objectIdStr && swfVersionStr) {
37161                 var regObj = {};
37162                 regObj.id = objectIdStr;
37163                 regObj.swfVersion = swfVersionStr;
37164                 regObj.expressInstall = xiSwfUrlStr;
37165                 regObj.callbackFn = callbackFn;
37166                 regObjArr[regObjArr.length] = regObj;
37167                 setVisibility(objectIdStr, false);
37168             }
37169             else if (callbackFn) {
37170                 callbackFn({success:false, id:objectIdStr});
37171             }
37172         },
37173         
37174         getObjectById: function(objectIdStr) {
37175             if (ua.w3) {
37176                 return getObjectById(objectIdStr);
37177             }
37178         },
37179         
37180         embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {
37181             var callbackObj = {success:false, id:replaceElemIdStr};
37182             if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
37183                 setVisibility(replaceElemIdStr, false);
37184                 addDomLoadEvent(function() {
37185                     widthStr += ""; 
37186                     heightStr += "";
37187                     var att = {};
37188                     if (attObj && typeof attObj === OBJECT) {
37189                         for (var i in attObj) { 
37190                             att[i] = attObj[i];
37191                         }
37192                     }
37193                     att.data = swfUrlStr;
37194                     att.width = widthStr;
37195                     att.height = heightStr;
37196                     var par = {}; 
37197                     if (parObj && typeof parObj === OBJECT) {
37198                         for (var j in parObj) { 
37199                             par[j] = parObj[j];
37200                         }
37201                     }
37202                     if (flashvarsObj && typeof flashvarsObj === OBJECT) {
37203                         for (var k in flashvarsObj) { 
37204                             if (typeof par.flashvars != UNDEF) {
37205                                 par.flashvars += "&" + k + "=" + flashvarsObj[k];
37206                             }
37207                             else {
37208                                 par.flashvars = k + "=" + flashvarsObj[k];
37209                             }
37210                         }
37211                     }
37212                     if (hasPlayerVersion(swfVersionStr)) { 
37213                         var obj = createSWF(att, par, replaceElemIdStr);
37214                         if (att.id == replaceElemIdStr) {
37215                             setVisibility(replaceElemIdStr, true);
37216                         }
37217                         callbackObj.success = true;
37218                         callbackObj.ref = obj;
37219                     }
37220                     else if (xiSwfUrlStr && canExpressInstall()) { 
37221                         att.data = xiSwfUrlStr;
37222                         showExpressInstall(att, par, replaceElemIdStr, callbackFn);
37223                         return;
37224                     }
37225                     else { 
37226                         setVisibility(replaceElemIdStr, true);
37227                     }
37228                     if (callbackFn) { callbackFn(callbackObj); }
37229                 });
37230             }
37231             else if (callbackFn) { callbackFn(callbackObj); }
37232         },
37233         
37234         switchOffAutoHideShow: function() {
37235             autoHideShow = false;
37236         },
37237         
37238         ua: ua,
37239         
37240         getFlashPlayerVersion: function() {
37241             return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };
37242         },
37243         
37244         hasFlashPlayerVersion: hasPlayerVersion,
37245         
37246         createSWF: function(attObj, parObj, replaceElemIdStr) {
37247             if (ua.w3) {
37248                 return createSWF(attObj, parObj, replaceElemIdStr);
37249             }
37250             else {
37251                 return undefined;
37252             }
37253         },
37254         
37255         showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) {
37256             if (ua.w3 && canExpressInstall()) {
37257                 showExpressInstall(att, par, replaceElemIdStr, callbackFn);
37258             }
37259         },
37260         
37261         removeSWF: function(objElemIdStr) {
37262             if (ua.w3) {
37263                 removeSWF(objElemIdStr);
37264             }
37265         },
37266         
37267         createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) {
37268             if (ua.w3) {
37269                 createCSS(selStr, declStr, mediaStr, newStyleBoolean);
37270             }
37271         },
37272         
37273         addDomLoadEvent: addDomLoadEvent,
37274         
37275         addLoadEvent: addLoadEvent,
37276         
37277         getQueryParamValue: function(param) {
37278             var q = doc.location.search || doc.location.hash;
37279             if (q) {
37280                 if (/\?/.test(q)) { q = q.split("?")[1]; } 
37281                 if (param == null) {
37282                     return urlEncodeIfNecessary(q);
37283                 }
37284                 var pairs = q.split("&");
37285                 for (var i = 0; i < pairs.length; i++) {
37286                     if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
37287                         return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));
37288                     }
37289                 }
37290             }
37291             return "";
37292         },
37293         
37294         
37295         expressInstallCallback: function() {
37296             if (isExpressInstallActive) {
37297                 var obj = getElementById(EXPRESS_INSTALL_ID);
37298                 if (obj && storedAltContent) {
37299                     obj.parentNode.replaceChild(storedAltContent, obj);
37300                     if (storedAltContentId) {
37301                         setVisibility(storedAltContentId, true);
37302                         if (ua.ie && ua.win) { storedAltContent.style.display = "block"; }
37303                     }
37304                     if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); }
37305                 }
37306                 isExpressInstallActive = false;
37307             } 
37308         }
37309     };
37310 }();
37311
37312 Ext.FlashComponent = Ext.extend(Ext.BoxComponent, {
37313     
37314     flashVersion : '9.0.115',
37315
37316     
37317     backgroundColor: '#ffffff',
37318
37319     
37320     wmode: 'opaque',
37321
37322     
37323     flashVars: undefined,
37324
37325     
37326     flashParams: undefined,
37327
37328     
37329     url: undefined,
37330     swfId : undefined,
37331     swfWidth: '100%',
37332     swfHeight: '100%',
37333
37334     
37335     expressInstall: false,
37336
37337     initComponent : function(){
37338         Ext.FlashComponent.superclass.initComponent.call(this);
37339
37340         this.addEvents(
37341             
37342             'initialize'
37343         );
37344     },
37345
37346     onRender : function(){
37347         Ext.FlashComponent.superclass.onRender.apply(this, arguments);
37348
37349         var params = Ext.apply({
37350             allowScriptAccess: 'always',
37351             bgcolor: this.backgroundColor,
37352             wmode: this.wmode
37353         }, this.flashParams), vars = Ext.apply({
37354             allowedDomain: document.location.hostname,
37355             YUISwfId: this.getId(),
37356             YUIBridgeCallback: 'Ext.FlashEventProxy.onEvent'
37357         }, this.flashVars);
37358
37359         new swfobject.embedSWF(this.url, this.id, this.swfWidth, this.swfHeight, this.flashVersion,
37360             this.expressInstall ? Ext.FlashComponent.EXPRESS_INSTALL_URL : undefined, vars, params);
37361
37362         this.swf = Ext.getDom(this.id);
37363         this.el = Ext.get(this.swf);
37364     },
37365
37366     getSwfId : function(){
37367         return this.swfId || (this.swfId = "extswf" + (++Ext.Component.AUTO_ID));
37368     },
37369
37370     getId : function(){
37371         return this.id || (this.id = "extflashcmp" + (++Ext.Component.AUTO_ID));
37372     },
37373
37374     onFlashEvent : function(e){
37375         switch(e.type){
37376             case "swfReady":
37377                 this.initSwf();
37378                 return;
37379             case "log":
37380                 return;
37381         }
37382         e.component = this;
37383         this.fireEvent(e.type.toLowerCase().replace(/event$/, ''), e);
37384     },
37385
37386     initSwf : function(){
37387         this.onSwfReady(!!this.isInitialized);
37388         this.isInitialized = true;
37389         this.fireEvent('initialize', this);
37390     },
37391
37392     beforeDestroy: function(){
37393         if(this.rendered){
37394             swfobject.removeSWF(this.swf.id);
37395         }
37396         Ext.FlashComponent.superclass.beforeDestroy.call(this);
37397     },
37398
37399     onSwfReady : Ext.emptyFn
37400 });
37401
37402
37403 Ext.FlashComponent.EXPRESS_INSTALL_URL = 'http:/' + '/swfobject.googlecode.com/svn/trunk/swfobject/expressInstall.swf';
37404
37405 Ext.reg('flash', Ext.FlashComponent);
37406 Ext.FlashEventProxy = {
37407     onEvent : function(id, e){
37408         var fp = Ext.getCmp(id);
37409         if(fp){
37410             fp.onFlashEvent(e);
37411         }else{
37412             arguments.callee.defer(10, this, [id, e]);
37413         }
37414     }
37415 };
37416
37417  Ext.chart.Chart = Ext.extend(Ext.FlashComponent, {
37418     refreshBuffer: 100,
37419
37420     
37421
37422     
37423     chartStyle: {
37424         padding: 10,
37425         animationEnabled: true,
37426         font: {
37427             name: 'Tahoma',
37428             color: 0x444444,
37429             size: 11
37430         },
37431         dataTip: {
37432             padding: 5,
37433             border: {
37434                 color: 0x99bbe8,
37435                 size:1
37436             },
37437             background: {
37438                 color: 0xDAE7F6,
37439                 alpha: .9
37440             },
37441             font: {
37442                 name: 'Tahoma',
37443                 color: 0x15428B,
37444                 size: 10,
37445                 bold: true
37446             }
37447         }
37448     },
37449
37450     
37451
37452     
37453     extraStyle: null,
37454
37455     
37456     seriesStyles: null,
37457
37458     
37459     disableCaching: Ext.isIE || Ext.isOpera,
37460     disableCacheParam: '_dc',
37461
37462     initComponent : function(){
37463         Ext.chart.Chart.superclass.initComponent.call(this);
37464         if(!this.url){
37465             this.url = Ext.chart.Chart.CHART_URL;
37466         }
37467         if(this.disableCaching){
37468             this.url = Ext.urlAppend(this.url, String.format('{0}={1}', this.disableCacheParam, new Date().getTime()));
37469         }
37470         this.addEvents(
37471             'itemmouseover',
37472             'itemmouseout',
37473             'itemclick',
37474             'itemdoubleclick',
37475             'itemdragstart',
37476             'itemdrag',
37477             'itemdragend',
37478             
37479             'beforerefresh',
37480             
37481             'refresh'
37482         );
37483         this.store = Ext.StoreMgr.lookup(this.store);
37484     },
37485
37486     
37487      setStyle: function(name, value){
37488          this.swf.setStyle(name, Ext.encode(value));
37489      },
37490
37491     
37492     setStyles: function(styles){
37493         this.swf.setStyles(Ext.encode(styles));
37494     },
37495
37496     
37497     setSeriesStyles: function(styles){
37498         this.seriesStyles = styles;
37499         var s = [];
37500         Ext.each(styles, function(style){
37501             s.push(Ext.encode(style));
37502         });
37503         this.swf.setSeriesStyles(s);
37504     },
37505
37506     setCategoryNames : function(names){
37507         this.swf.setCategoryNames(names);
37508     },
37509
37510     setLegendRenderer : function(fn, scope){
37511         var chart = this;
37512         scope = scope || chart;
37513         chart.removeFnProxy(chart.legendFnName);
37514         chart.legendFnName = chart.createFnProxy(function(name){
37515             return fn.call(scope, name);
37516         });
37517         chart.swf.setLegendLabelFunction(chart.legendFnName);
37518     },
37519
37520     setTipRenderer : function(fn, scope){
37521         var chart = this;
37522         scope = scope || chart;
37523         chart.removeFnProxy(chart.tipFnName);
37524         chart.tipFnName = chart.createFnProxy(function(item, index, series){
37525             var record = chart.store.getAt(index);
37526             return fn.call(scope, chart, record, index, series);
37527         });
37528         chart.swf.setDataTipFunction(chart.tipFnName);
37529     },
37530
37531     setSeries : function(series){
37532         this.series = series;
37533         this.refresh();
37534     },
37535
37536     
37537     bindStore : function(store, initial){
37538         if(!initial && this.store){
37539             if(store !== this.store && this.store.autoDestroy){
37540                 this.store.destroy();
37541             }else{
37542                 this.store.un("datachanged", this.refresh, this);
37543                 this.store.un("add", this.delayRefresh, this);
37544                 this.store.un("remove", this.delayRefresh, this);
37545                 this.store.un("update", this.delayRefresh, this);
37546                 this.store.un("clear", this.refresh, this);
37547             }
37548         }
37549         if(store){
37550             store = Ext.StoreMgr.lookup(store);
37551             store.on({
37552                 scope: this,
37553                 datachanged: this.refresh,
37554                 add: this.delayRefresh,
37555                 remove: this.delayRefresh,
37556                 update: this.delayRefresh,
37557                 clear: this.refresh
37558             });
37559         }
37560         this.store = store;
37561         if(store && !initial){
37562             this.refresh();
37563         }
37564     },
37565
37566     onSwfReady : function(isReset){
37567         Ext.chart.Chart.superclass.onSwfReady.call(this, isReset);
37568         var ref;
37569         this.swf.setType(this.type);
37570
37571         if(this.chartStyle){
37572             this.setStyles(Ext.apply({}, this.extraStyle, this.chartStyle));
37573         }
37574
37575         if(this.categoryNames){
37576             this.setCategoryNames(this.categoryNames);
37577         }
37578
37579         if(this.tipRenderer){
37580             ref = this.getFunctionRef(this.tipRenderer);
37581             this.setTipRenderer(ref.fn, ref.scope);
37582         }
37583         if(this.legendRenderer){
37584             ref = this.getFunctionRef(this.legendRenderer);
37585             this.setLegendRenderer(ref.fn, ref.scope);
37586         }
37587         if(!isReset){
37588             this.bindStore(this.store, true);
37589         }
37590         this.refresh.defer(10, this);
37591     },
37592
37593     delayRefresh : function(){
37594         if(!this.refreshTask){
37595             this.refreshTask = new Ext.util.DelayedTask(this.refresh, this);
37596         }
37597         this.refreshTask.delay(this.refreshBuffer);
37598     },
37599
37600     refresh : function(){
37601         if(this.fireEvent('beforerefresh', this) !== false){
37602             var styleChanged = false;
37603             
37604             var data = [], rs = this.store.data.items;
37605             for(var j = 0, len = rs.length; j < len; j++){
37606                 data[j] = rs[j].data;
37607             }
37608             
37609             
37610             var dataProvider = [];
37611             var seriesCount = 0;
37612             var currentSeries = null;
37613             var i = 0;
37614             if(this.series){
37615                 seriesCount = this.series.length;
37616                 for(i = 0; i < seriesCount; i++){
37617                     currentSeries = this.series[i];
37618                     var clonedSeries = {};
37619                     for(var prop in currentSeries){
37620                         if(prop == "style" && currentSeries.style !== null){
37621                             clonedSeries.style = Ext.encode(currentSeries.style);
37622                             styleChanged = true;
37623                             
37624                             
37625                             
37626                             
37627                         } else{
37628                             clonedSeries[prop] = currentSeries[prop];
37629                         }
37630                     }
37631                     dataProvider.push(clonedSeries);
37632                 }
37633             }
37634
37635             if(seriesCount > 0){
37636                 for(i = 0; i < seriesCount; i++){
37637                     currentSeries = dataProvider[i];
37638                     if(!currentSeries.type){
37639                         currentSeries.type = this.type;
37640                     }
37641                     currentSeries.dataProvider = data;
37642                 }
37643             } else{
37644                 dataProvider.push({type: this.type, dataProvider: data});
37645             }
37646             this.swf.setDataProvider(dataProvider);
37647             if(this.seriesStyles){
37648                 this.setSeriesStyles(this.seriesStyles);
37649             }
37650             this.fireEvent('refresh', this);
37651         }
37652     },
37653
37654     
37655     createFnProxy : function(fn){
37656         var fnName = 'extFnProxy' + (++Ext.chart.Chart.PROXY_FN_ID);
37657         Ext.chart.Chart.proxyFunction[fnName] = fn;
37658         return 'Ext.chart.Chart.proxyFunction.' + fnName;
37659     },
37660
37661     
37662     removeFnProxy : function(fn){
37663         if(!Ext.isEmpty(fn)){
37664             fn = fn.replace('Ext.chart.Chart.proxyFunction.', '');
37665             delete Ext.chart.Chart.proxyFunction[fn];
37666         }
37667     },
37668
37669     
37670     getFunctionRef : function(val){
37671         if(Ext.isFunction(val)){
37672             return {
37673                 fn: val,
37674                 scope: this
37675             };
37676         }else{
37677             return {
37678                 fn: val.fn,
37679                 scope: val.scope || this
37680             };
37681         }
37682     },
37683
37684     
37685     onDestroy: function(){
37686         if (this.refreshTask && this.refreshTask.cancel){
37687             this.refreshTask.cancel();
37688         }
37689         Ext.chart.Chart.superclass.onDestroy.call(this);
37690         this.bindStore(null);
37691         this.removeFnProxy(this.tipFnName);
37692         this.removeFnProxy(this.legendFnName);
37693     }
37694 });
37695 Ext.reg('chart', Ext.chart.Chart);
37696 Ext.chart.Chart.PROXY_FN_ID = 0;
37697 Ext.chart.Chart.proxyFunction = {};
37698
37699
37700 Ext.chart.Chart.CHART_URL = 'http:/' + '/yui.yahooapis.com/2.8.2/build/charts/assets/charts.swf';
37701
37702
37703 Ext.chart.PieChart = Ext.extend(Ext.chart.Chart, {
37704     type: 'pie',
37705
37706     onSwfReady : function(isReset){
37707         Ext.chart.PieChart.superclass.onSwfReady.call(this, isReset);
37708
37709         this.setDataField(this.dataField);
37710         this.setCategoryField(this.categoryField);
37711     },
37712
37713     setDataField : function(field){
37714         this.dataField = field;
37715         this.swf.setDataField(field);
37716     },
37717
37718     setCategoryField : function(field){
37719         this.categoryField = field;
37720         this.swf.setCategoryField(field);
37721     }
37722 });
37723 Ext.reg('piechart', Ext.chart.PieChart);
37724
37725
37726 Ext.chart.CartesianChart = Ext.extend(Ext.chart.Chart, {
37727     onSwfReady : function(isReset){
37728         Ext.chart.CartesianChart.superclass.onSwfReady.call(this, isReset);
37729         this.labelFn = [];
37730         if(this.xField){
37731             this.setXField(this.xField);
37732         }
37733         if(this.yField){
37734             this.setYField(this.yField);
37735         }
37736         if(this.xAxis){
37737             this.setXAxis(this.xAxis);
37738         }
37739         if(this.xAxes){
37740             this.setXAxes(this.xAxes);
37741         }
37742         if(this.yAxis){
37743             this.setYAxis(this.yAxis);
37744         }
37745         if(this.yAxes){
37746             this.setYAxes(this.yAxes);
37747         }
37748         if(Ext.isDefined(this.constrainViewport)){
37749             this.swf.setConstrainViewport(this.constrainViewport);
37750         }
37751     },
37752
37753     setXField : function(value){
37754         this.xField = value;
37755         this.swf.setHorizontalField(value);
37756     },
37757
37758     setYField : function(value){
37759         this.yField = value;
37760         this.swf.setVerticalField(value);
37761     },
37762
37763     setXAxis : function(value){
37764         this.xAxis = this.createAxis('xAxis', value);
37765         this.swf.setHorizontalAxis(this.xAxis);
37766     },
37767
37768     setXAxes : function(value){
37769         var axis;
37770         for(var i = 0; i < value.length; i++) {
37771             axis = this.createAxis('xAxis' + i, value[i]);
37772             this.swf.setHorizontalAxis(axis);
37773         }
37774     },
37775
37776     setYAxis : function(value){
37777         this.yAxis = this.createAxis('yAxis', value);
37778         this.swf.setVerticalAxis(this.yAxis);
37779     },
37780
37781     setYAxes : function(value){
37782         var axis;
37783         for(var i = 0; i < value.length; i++) {
37784             axis = this.createAxis('yAxis' + i, value[i]);
37785             this.swf.setVerticalAxis(axis);
37786         }
37787     },
37788
37789     createAxis : function(axis, value){
37790         var o = Ext.apply({}, value),
37791             ref,
37792             old;
37793
37794         if(this[axis]){
37795             old = this[axis].labelFunction;
37796             this.removeFnProxy(old);
37797             this.labelFn.remove(old);
37798         }
37799         if(o.labelRenderer){
37800             ref = this.getFunctionRef(o.labelRenderer);
37801             o.labelFunction = this.createFnProxy(function(v){
37802                 return ref.fn.call(ref.scope, v);
37803             });
37804             delete o.labelRenderer;
37805             this.labelFn.push(o.labelFunction);
37806         }
37807         if(axis.indexOf('xAxis') > -1 && o.position == 'left'){
37808             o.position = 'bottom';
37809         }
37810         return o;
37811     },
37812
37813     onDestroy : function(){
37814         Ext.chart.CartesianChart.superclass.onDestroy.call(this);
37815         Ext.each(this.labelFn, function(fn){
37816             this.removeFnProxy(fn);
37817         }, this);
37818     }
37819 });
37820 Ext.reg('cartesianchart', Ext.chart.CartesianChart);
37821
37822
37823 Ext.chart.LineChart = Ext.extend(Ext.chart.CartesianChart, {
37824     type: 'line'
37825 });
37826 Ext.reg('linechart', Ext.chart.LineChart);
37827
37828
37829 Ext.chart.ColumnChart = Ext.extend(Ext.chart.CartesianChart, {
37830     type: 'column'
37831 });
37832 Ext.reg('columnchart', Ext.chart.ColumnChart);
37833
37834
37835 Ext.chart.StackedColumnChart = Ext.extend(Ext.chart.CartesianChart, {
37836     type: 'stackcolumn'
37837 });
37838 Ext.reg('stackedcolumnchart', Ext.chart.StackedColumnChart);
37839
37840
37841 Ext.chart.BarChart = Ext.extend(Ext.chart.CartesianChart, {
37842     type: 'bar'
37843 });
37844 Ext.reg('barchart', Ext.chart.BarChart);
37845
37846
37847 Ext.chart.StackedBarChart = Ext.extend(Ext.chart.CartesianChart, {
37848     type: 'stackbar'
37849 });
37850 Ext.reg('stackedbarchart', Ext.chart.StackedBarChart);
37851
37852
37853
37854
37855 Ext.chart.Axis = function(config){
37856     Ext.apply(this, config);
37857 };
37858
37859 Ext.chart.Axis.prototype =
37860 {
37861     
37862     type: null,
37863
37864     
37865     orientation: "horizontal",
37866
37867     
37868     reverse: false,
37869
37870     
37871     labelFunction: null,
37872
37873     
37874     hideOverlappingLabels: true,
37875
37876     
37877     labelSpacing: 2
37878 };
37879
37880
37881 Ext.chart.NumericAxis = Ext.extend(Ext.chart.Axis, {
37882     type: "numeric",
37883
37884     
37885     minimum: NaN,
37886
37887     
37888     maximum: NaN,
37889
37890     
37891     majorUnit: NaN,
37892
37893     
37894     minorUnit: NaN,
37895
37896     
37897     snapToUnits: true,
37898
37899     
37900     alwaysShowZero: true,
37901
37902     
37903     scale: "linear",
37904
37905     
37906     roundMajorUnit: true,
37907
37908     
37909     calculateByLabelSize: true,
37910
37911     
37912     position: 'left',
37913
37914     
37915     adjustMaximumByMajorUnit: true,
37916
37917     
37918     adjustMinimumByMajorUnit: true
37919
37920 });
37921
37922
37923 Ext.chart.TimeAxis = Ext.extend(Ext.chart.Axis, {
37924     type: "time",
37925
37926     
37927     minimum: null,
37928
37929     
37930     maximum: null,
37931
37932     
37933     majorUnit: NaN,
37934
37935     
37936     majorTimeUnit: null,
37937
37938     
37939     minorUnit: NaN,
37940
37941     
37942     minorTimeUnit: null,
37943
37944     
37945     snapToUnits: true,
37946
37947     
37948     stackingEnabled: false,
37949
37950     
37951     calculateByLabelSize: true
37952
37953 });
37954
37955
37956 Ext.chart.CategoryAxis = Ext.extend(Ext.chart.Axis, {
37957     type: "category",
37958
37959     
37960     categoryNames: null,
37961
37962     
37963     calculateCategoryCount: false
37964
37965 });
37966
37967
37968 Ext.chart.Series = function(config) { Ext.apply(this, config); };
37969
37970 Ext.chart.Series.prototype =
37971 {
37972     
37973     type: null,
37974
37975     
37976     displayName: null
37977 };
37978
37979
37980 Ext.chart.CartesianSeries = Ext.extend(Ext.chart.Series, {
37981     
37982     xField: null,
37983
37984     
37985     yField: null,
37986
37987     
37988     showInLegend: true,
37989
37990     
37991     axis: 'primary'
37992 });
37993
37994
37995 Ext.chart.ColumnSeries = Ext.extend(Ext.chart.CartesianSeries, {
37996     type: "column"
37997 });
37998
37999
38000 Ext.chart.LineSeries = Ext.extend(Ext.chart.CartesianSeries, {
38001     type: "line"
38002 });
38003
38004
38005 Ext.chart.BarSeries = Ext.extend(Ext.chart.CartesianSeries, {
38006     type: "bar"
38007 });
38008
38009
38010
38011 Ext.chart.PieSeries = Ext.extend(Ext.chart.Series, {
38012     type: "pie",
38013     dataField: null,
38014     categoryField: null
38015 });
38016 Ext.menu.Menu = Ext.extend(Ext.Container, {
38017     
38018     
38019     
38020     minWidth : 120,
38021     
38022     shadow : 'sides',
38023     
38024     subMenuAlign : 'tl-tr?',
38025     
38026     defaultAlign : 'tl-bl?',
38027     
38028     allowOtherMenus : false,
38029     
38030     ignoreParentClicks : false,
38031     
38032     enableScrolling : true,
38033     
38034     maxHeight : null,
38035     
38036     scrollIncrement : 24,
38037     
38038     showSeparator : true,
38039     
38040     defaultOffsets : [0, 0],
38041
38042     
38043     plain : false,
38044
38045     
38046     floating : true,
38047
38048
38049     
38050     zIndex: 15000,
38051
38052     
38053     hidden : true,
38054
38055     
38056     layout : 'menu',
38057     hideMode : 'offsets',    
38058     scrollerHeight : 8,
38059     autoLayout : true,       
38060     defaultType : 'menuitem',
38061     bufferResize : false,
38062
38063     initComponent : function(){
38064         if(Ext.isArray(this.initialConfig)){
38065             Ext.apply(this, {items:this.initialConfig});
38066         }
38067         this.addEvents(
38068             
38069             'click',
38070             
38071             'mouseover',
38072             
38073             'mouseout',
38074             
38075             'itemclick'
38076         );
38077         Ext.menu.MenuMgr.register(this);
38078         if(this.floating){
38079             Ext.EventManager.onWindowResize(this.hide, this);
38080         }else{
38081             if(this.initialConfig.hidden !== false){
38082                 this.hidden = false;
38083             }
38084             this.internalDefaults = {hideOnClick: false};
38085         }
38086         Ext.menu.Menu.superclass.initComponent.call(this);
38087         if(this.autoLayout){
38088             var fn = this.doLayout.createDelegate(this, []);
38089             this.on({
38090                 add: fn,
38091                 remove: fn
38092             });
38093         }
38094     },
38095
38096     
38097     getLayoutTarget : function() {
38098         return this.ul;
38099     },
38100
38101     
38102     onRender : function(ct, position){
38103         if(!ct){
38104             ct = Ext.getBody();
38105         }
38106
38107         var dh = {
38108             id: this.getId(),
38109             cls: 'x-menu ' + ((this.floating) ? 'x-menu-floating x-layer ' : '') + (this.cls || '') + (this.plain ? ' x-menu-plain' : '') + (this.showSeparator ? '' : ' x-menu-nosep'),
38110             style: this.style,
38111             cn: [
38112                 {tag: 'a', cls: 'x-menu-focus', href: '#', onclick: 'return false;', tabIndex: '-1'},
38113                 {tag: 'ul', cls: 'x-menu-list'}
38114             ]
38115         };
38116         if(this.floating){
38117             this.el = new Ext.Layer({
38118                 shadow: this.shadow,
38119                 dh: dh,
38120                 constrain: false,
38121                 parentEl: ct,
38122                 zindex: this.zIndex
38123             });
38124         }else{
38125             this.el = ct.createChild(dh);
38126         }
38127         Ext.menu.Menu.superclass.onRender.call(this, ct, position);
38128
38129         if(!this.keyNav){
38130             this.keyNav = new Ext.menu.MenuNav(this);
38131         }
38132         
38133         this.focusEl = this.el.child('a.x-menu-focus');
38134         this.ul = this.el.child('ul.x-menu-list');
38135         this.mon(this.ul, {
38136             scope: this,
38137             click: this.onClick,
38138             mouseover: this.onMouseOver,
38139             mouseout: this.onMouseOut
38140         });
38141         if(this.enableScrolling){
38142             this.mon(this.el, {
38143                 scope: this,
38144                 delegate: '.x-menu-scroller',
38145                 click: this.onScroll,
38146                 mouseover: this.deactivateActive
38147             });
38148         }
38149     },
38150
38151     
38152     findTargetItem : function(e){
38153         var t = e.getTarget('.x-menu-list-item', this.ul, true);
38154         if(t && t.menuItemId){
38155             return this.items.get(t.menuItemId);
38156         }
38157     },
38158
38159     
38160     onClick : function(e){
38161         var t = this.findTargetItem(e);
38162         if(t){
38163             if(t.isFormField){
38164                 this.setActiveItem(t);
38165             }else if(t instanceof Ext.menu.BaseItem){
38166                 if(t.menu && this.ignoreParentClicks){
38167                     t.expandMenu();
38168                     e.preventDefault();
38169                 }else if(t.onClick){
38170                     t.onClick(e);
38171                     this.fireEvent('click', this, t, e);
38172                 }
38173             }
38174         }
38175     },
38176
38177     
38178     setActiveItem : function(item, autoExpand){
38179         if(item != this.activeItem){
38180             this.deactivateActive();
38181             if((this.activeItem = item).isFormField){
38182                 item.focus();
38183             }else{
38184                 item.activate(autoExpand);
38185             }
38186         }else if(autoExpand){
38187             item.expandMenu();
38188         }
38189     },
38190
38191     deactivateActive : function(){
38192         var a = this.activeItem;
38193         if(a){
38194             if(a.isFormField){
38195                 
38196                 if(a.collapse){
38197                     a.collapse();
38198                 }
38199             }else{
38200                 a.deactivate();
38201             }
38202             delete this.activeItem;
38203         }
38204     },
38205
38206     
38207     tryActivate : function(start, step){
38208         var items = this.items;
38209         for(var i = start, len = items.length; i >= 0 && i < len; i+= step){
38210             var item = items.get(i);
38211             if(item.isVisible() && !item.disabled && (item.canActivate || item.isFormField)){
38212                 this.setActiveItem(item, false);
38213                 return item;
38214             }
38215         }
38216         return false;
38217     },
38218
38219     
38220     onMouseOver : function(e){
38221         var t = this.findTargetItem(e);
38222         if(t){
38223             if(t.canActivate && !t.disabled){
38224                 this.setActiveItem(t, true);
38225             }
38226         }
38227         this.over = true;
38228         this.fireEvent('mouseover', this, e, t);
38229     },
38230
38231     
38232     onMouseOut : function(e){
38233         var t = this.findTargetItem(e);
38234         if(t){
38235             if(t == this.activeItem && t.shouldDeactivate && t.shouldDeactivate(e)){
38236                 this.activeItem.deactivate();
38237                 delete this.activeItem;
38238             }
38239         }
38240         this.over = false;
38241         this.fireEvent('mouseout', this, e, t);
38242     },
38243
38244     
38245     onScroll : function(e, t){
38246         if(e){
38247             e.stopEvent();
38248         }
38249         var ul = this.ul.dom, top = Ext.fly(t).is('.x-menu-scroller-top');
38250         ul.scrollTop += this.scrollIncrement * (top ? -1 : 1);
38251         if(top ? ul.scrollTop <= 0 : ul.scrollTop + this.activeMax >= ul.scrollHeight){
38252            this.onScrollerOut(null, t);
38253         }
38254     },
38255
38256     
38257     onScrollerIn : function(e, t){
38258         var ul = this.ul.dom, top = Ext.fly(t).is('.x-menu-scroller-top');
38259         if(top ? ul.scrollTop > 0 : ul.scrollTop + this.activeMax < ul.scrollHeight){
38260             Ext.fly(t).addClass(['x-menu-item-active', 'x-menu-scroller-active']);
38261         }
38262     },
38263
38264     
38265     onScrollerOut : function(e, t){
38266         Ext.fly(t).removeClass(['x-menu-item-active', 'x-menu-scroller-active']);
38267     },
38268
38269     
38270     show : function(el, pos, parentMenu){
38271         if(this.floating){
38272             this.parentMenu = parentMenu;
38273             if(!this.el){
38274                 this.render();
38275                 this.doLayout(false, true);
38276             }
38277             this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign, this.defaultOffsets), parentMenu);
38278         }else{
38279             Ext.menu.Menu.superclass.show.call(this);
38280         }
38281     },
38282
38283     
38284     showAt : function(xy, parentMenu){
38285         if(this.fireEvent('beforeshow', this) !== false){
38286             this.parentMenu = parentMenu;
38287             if(!this.el){
38288                 this.render();
38289             }
38290             if(this.enableScrolling){
38291                 
38292                 this.el.setXY(xy);
38293                 
38294                 xy[1] = this.constrainScroll(xy[1]);
38295                 xy = [this.el.adjustForConstraints(xy)[0], xy[1]];
38296             }else{
38297                 
38298                 xy = this.el.adjustForConstraints(xy);
38299             }
38300             this.el.setXY(xy);
38301             this.el.show();
38302             Ext.menu.Menu.superclass.onShow.call(this);
38303             if(Ext.isIE){
38304                 
38305                 this.fireEvent('autosize', this);
38306                 if(!Ext.isIE8){
38307                     this.el.repaint();
38308                 }
38309             }
38310             this.hidden = false;
38311             this.focus();
38312             this.fireEvent('show', this);
38313         }
38314     },
38315
38316     constrainScroll : function(y){
38317         var max, full = this.ul.setHeight('auto').getHeight(),
38318             returnY = y, normalY, parentEl, scrollTop, viewHeight;
38319         if(this.floating){
38320             parentEl = Ext.fly(this.el.dom.parentNode);
38321             scrollTop = parentEl.getScroll().top;
38322             viewHeight = parentEl.getViewSize().height;
38323             
38324             
38325             normalY = y - scrollTop;
38326             max = this.maxHeight ? this.maxHeight : viewHeight - normalY;
38327             if(full > viewHeight) {
38328                 max = viewHeight;
38329                 
38330                 returnY = y - normalY;
38331             } else if(max < full) {
38332                 returnY = y - (full - max);
38333                 max = full;
38334             }
38335         }else{
38336             max = this.getHeight();
38337         }
38338         
38339         if (this.maxHeight){
38340             max = Math.min(this.maxHeight, max);
38341         }
38342         if(full > max && max > 0){
38343             this.activeMax = max - this.scrollerHeight * 2 - this.el.getFrameWidth('tb') - Ext.num(this.el.shadowOffset, 0);
38344             this.ul.setHeight(this.activeMax);
38345             this.createScrollers();
38346             this.el.select('.x-menu-scroller').setDisplayed('');
38347         }else{
38348             this.ul.setHeight(full);
38349             this.el.select('.x-menu-scroller').setDisplayed('none');
38350         }
38351         this.ul.dom.scrollTop = 0;
38352         return returnY;
38353     },
38354
38355     createScrollers : function(){
38356         if(!this.scroller){
38357             this.scroller = {
38358                 pos: 0,
38359                 top: this.el.insertFirst({
38360                     tag: 'div',
38361                     cls: 'x-menu-scroller x-menu-scroller-top',
38362                     html: '&#160;'
38363                 }),
38364                 bottom: this.el.createChild({
38365                     tag: 'div',
38366                     cls: 'x-menu-scroller x-menu-scroller-bottom',
38367                     html: '&#160;'
38368                 })
38369             };
38370             this.scroller.top.hover(this.onScrollerIn, this.onScrollerOut, this);
38371             this.scroller.topRepeater = new Ext.util.ClickRepeater(this.scroller.top, {
38372                 listeners: {
38373                     click: this.onScroll.createDelegate(this, [null, this.scroller.top], false)
38374                 }
38375             });
38376             this.scroller.bottom.hover(this.onScrollerIn, this.onScrollerOut, this);
38377             this.scroller.bottomRepeater = new Ext.util.ClickRepeater(this.scroller.bottom, {
38378                 listeners: {
38379                     click: this.onScroll.createDelegate(this, [null, this.scroller.bottom], false)
38380                 }
38381             });
38382         }
38383     },
38384
38385     onLayout : function(){
38386         if(this.isVisible()){
38387             if(this.enableScrolling){
38388                 this.constrainScroll(this.el.getTop());
38389             }
38390             if(this.floating){
38391                 this.el.sync();
38392             }
38393         }
38394     },
38395
38396     focus : function(){
38397         if(!this.hidden){
38398             this.doFocus.defer(50, this);
38399         }
38400     },
38401
38402     doFocus : function(){
38403         if(!this.hidden){
38404             this.focusEl.focus();
38405         }
38406     },
38407
38408     
38409     hide : function(deep){
38410         if (!this.isDestroyed) {
38411             this.deepHide = deep;
38412             Ext.menu.Menu.superclass.hide.call(this);
38413             delete this.deepHide;
38414         }
38415     },
38416
38417     
38418     onHide : function(){
38419         Ext.menu.Menu.superclass.onHide.call(this);
38420         this.deactivateActive();
38421         if(this.el && this.floating){
38422             this.el.hide();
38423         }
38424         var pm = this.parentMenu;
38425         if(this.deepHide === true && pm){
38426             if(pm.floating){
38427                 pm.hide(true);
38428             }else{
38429                 pm.deactivateActive();
38430             }
38431         }
38432     },
38433
38434     
38435     lookupComponent : function(c){
38436          if(Ext.isString(c)){
38437             c = (c == 'separator' || c == '-') ? new Ext.menu.Separator() : new Ext.menu.TextItem(c);
38438              this.applyDefaults(c);
38439          }else{
38440             if(Ext.isObject(c)){
38441                 c = this.getMenuItem(c);
38442             }else if(c.tagName || c.el){ 
38443                 c = new Ext.BoxComponent({
38444                     el: c
38445                 });
38446             }
38447          }
38448          return c;
38449     },
38450
38451     applyDefaults : function(c) {
38452         if (!Ext.isString(c)) {
38453             c = Ext.menu.Menu.superclass.applyDefaults.call(this, c);
38454             var d = this.internalDefaults;
38455             if(d){
38456                 if(c.events){
38457                     Ext.applyIf(c.initialConfig, d);
38458                     Ext.apply(c, d);
38459                 }else{
38460                     Ext.applyIf(c, d);
38461                 }
38462             }
38463         }
38464         return c;
38465     },
38466
38467     
38468     getMenuItem : function(config) {
38469         if (!config.isXType) {
38470             if (!config.xtype && Ext.isBoolean(config.checked)) {
38471                 return new Ext.menu.CheckItem(config);
38472             }
38473             return Ext.create(config, this.defaultType);
38474         }
38475         return config;
38476     },
38477
38478     
38479     addSeparator : function() {
38480         return this.add(new Ext.menu.Separator());
38481     },
38482
38483     
38484     addElement : function(el) {
38485         return this.add(new Ext.menu.BaseItem({
38486             el: el
38487         }));
38488     },
38489
38490     
38491     addItem : function(item) {
38492         return this.add(item);
38493     },
38494
38495     
38496     addMenuItem : function(config) {
38497         return this.add(this.getMenuItem(config));
38498     },
38499
38500     
38501     addText : function(text){
38502         return this.add(new Ext.menu.TextItem(text));
38503     },
38504
38505     
38506     onDestroy : function(){
38507         Ext.EventManager.removeResizeListener(this.hide, this);
38508         var pm = this.parentMenu;
38509         if(pm && pm.activeChild == this){
38510             delete pm.activeChild;
38511         }
38512         delete this.parentMenu;
38513         Ext.menu.Menu.superclass.onDestroy.call(this);
38514         Ext.menu.MenuMgr.unregister(this);
38515         if(this.keyNav) {
38516             this.keyNav.disable();
38517         }
38518         var s = this.scroller;
38519         if(s){
38520             Ext.destroy(s.topRepeater, s.bottomRepeater, s.top, s.bottom);
38521         }
38522         Ext.destroy(
38523             this.el,
38524             this.focusEl,
38525             this.ul
38526         );
38527     }
38528 });
38529
38530 Ext.reg('menu', Ext.menu.Menu);
38531
38532
38533 Ext.menu.MenuNav = Ext.extend(Ext.KeyNav, function(){
38534     function up(e, m){
38535         if(!m.tryActivate(m.items.indexOf(m.activeItem)-1, -1)){
38536             m.tryActivate(m.items.length-1, -1);
38537         }
38538     }
38539     function down(e, m){
38540         if(!m.tryActivate(m.items.indexOf(m.activeItem)+1, 1)){
38541             m.tryActivate(0, 1);
38542         }
38543     }
38544     return {
38545         constructor : function(menu){
38546             Ext.menu.MenuNav.superclass.constructor.call(this, menu.el);
38547             this.scope = this.menu = menu;
38548         },
38549
38550         doRelay : function(e, h){
38551             var k = e.getKey();
38552
38553             if (this.menu.activeItem && this.menu.activeItem.isFormField && k != e.TAB) {
38554                 return false;
38555             }
38556             if(!this.menu.activeItem && e.isNavKeyPress() && k != e.SPACE && k != e.RETURN){
38557                 this.menu.tryActivate(0, 1);
38558                 return false;
38559             }
38560             return h.call(this.scope || this, e, this.menu);
38561         },
38562
38563         tab: function(e, m) {
38564             e.stopEvent();
38565             if (e.shiftKey) {
38566                 up(e, m);
38567             } else {
38568                 down(e, m);
38569             }
38570         },
38571
38572         up : up,
38573
38574         down : down,
38575
38576         right : function(e, m){
38577             if(m.activeItem){
38578                 m.activeItem.expandMenu(true);
38579             }
38580         },
38581
38582         left : function(e, m){
38583             m.hide();
38584             if(m.parentMenu && m.parentMenu.activeItem){
38585                 m.parentMenu.activeItem.activate();
38586             }
38587         },
38588
38589         enter : function(e, m){
38590             if(m.activeItem){
38591                 e.stopPropagation();
38592                 m.activeItem.onClick(e);
38593                 m.fireEvent('click', this, m.activeItem);
38594                 return true;
38595             }
38596         }
38597     };
38598 }());
38599
38600 Ext.menu.MenuMgr = function(){
38601    var menus, active, groups = {}, attached = false, lastShow = new Date();
38602
38603    
38604    function init(){
38605        menus = {};
38606        active = new Ext.util.MixedCollection();
38607        Ext.getDoc().addKeyListener(27, function(){
38608            if(active.length > 0){
38609                hideAll();
38610            }
38611        });
38612    }
38613
38614    
38615    function hideAll(){
38616        if(active && active.length > 0){
38617            var c = active.clone();
38618            c.each(function(m){
38619                m.hide();
38620            });
38621            return true;
38622        }
38623        return false;
38624    }
38625
38626    
38627    function onHide(m){
38628        active.remove(m);
38629        if(active.length < 1){
38630            Ext.getDoc().un("mousedown", onMouseDown);
38631            attached = false;
38632        }
38633    }
38634
38635    
38636    function onShow(m){
38637        var last = active.last();
38638        lastShow = new Date();
38639        active.add(m);
38640        if(!attached){
38641            Ext.getDoc().on("mousedown", onMouseDown);
38642            attached = true;
38643        }
38644        if(m.parentMenu){
38645           m.getEl().setZIndex(parseInt(m.parentMenu.getEl().getStyle("z-index"), 10) + 3);
38646           m.parentMenu.activeChild = m;
38647        }else if(last && !last.isDestroyed && last.isVisible()){
38648           m.getEl().setZIndex(parseInt(last.getEl().getStyle("z-index"), 10) + 3);
38649        }
38650    }
38651
38652    
38653    function onBeforeHide(m){
38654        if(m.activeChild){
38655            m.activeChild.hide();
38656        }
38657        if(m.autoHideTimer){
38658            clearTimeout(m.autoHideTimer);
38659            delete m.autoHideTimer;
38660        }
38661    }
38662
38663    
38664    function onBeforeShow(m){
38665        var pm = m.parentMenu;
38666        if(!pm && !m.allowOtherMenus){
38667            hideAll();
38668        }else if(pm && pm.activeChild){
38669            pm.activeChild.hide();
38670        }
38671    }
38672
38673    
38674    function onMouseDown(e){
38675        if(lastShow.getElapsed() > 50 && active.length > 0 && !e.getTarget(".x-menu")){
38676            hideAll();
38677        }
38678    }
38679
38680    return {
38681
38682        
38683        hideAll : function(){
38684             return hideAll();
38685        },
38686
38687        
38688        register : function(menu){
38689            if(!menus){
38690                init();
38691            }
38692            menus[menu.id] = menu;
38693            menu.on({
38694                beforehide: onBeforeHide,
38695                hide: onHide,
38696                beforeshow: onBeforeShow,
38697                show: onShow
38698            });
38699        },
38700
38701         
38702        get : function(menu){
38703            if(typeof menu == "string"){ 
38704                if(!menus){  
38705                    return null;
38706                }
38707                return menus[menu];
38708            }else if(menu.events){  
38709                return menu;
38710            }else if(typeof menu.length == 'number'){ 
38711                return new Ext.menu.Menu({items:menu});
38712            }else{ 
38713                return Ext.create(menu, 'menu');
38714            }
38715        },
38716
38717        
38718        unregister : function(menu){
38719            delete menus[menu.id];
38720            menu.un("beforehide", onBeforeHide);
38721            menu.un("hide", onHide);
38722            menu.un("beforeshow", onBeforeShow);
38723            menu.un("show", onShow);
38724        },
38725
38726        
38727        registerCheckable : function(menuItem){
38728            var g = menuItem.group;
38729            if(g){
38730                if(!groups[g]){
38731                    groups[g] = [];
38732                }
38733                groups[g].push(menuItem);
38734            }
38735        },
38736
38737        
38738        unregisterCheckable : function(menuItem){
38739            var g = menuItem.group;
38740            if(g){
38741                groups[g].remove(menuItem);
38742            }
38743        },
38744        
38745        
38746        onCheckChange: function(item, state){
38747            if(item.group && state){
38748                var group = groups[item.group],
38749                    i = 0,
38750                    len = group.length,
38751                    current;
38752                    
38753                for(; i < len; i++){
38754                    current = group[i];
38755                    if(current != item){
38756                        current.setChecked(false);
38757                    }
38758                }
38759            }
38760        },
38761
38762        getCheckedItem : function(groupId){
38763            var g = groups[groupId];
38764            if(g){
38765                for(var i = 0, l = g.length; i < l; i++){
38766                    if(g[i].checked){
38767                        return g[i];
38768                    }
38769                }
38770            }
38771            return null;
38772        },
38773
38774        setCheckedItem : function(groupId, itemId){
38775            var g = groups[groupId];
38776            if(g){
38777                for(var i = 0, l = g.length; i < l; i++){
38778                    if(g[i].id == itemId){
38779                        g[i].setChecked(true);
38780                    }
38781                }
38782            }
38783            return null;
38784        }
38785    };
38786 }();
38787
38788 Ext.menu.BaseItem = Ext.extend(Ext.Component, {
38789     
38790     
38791     
38792     
38793     canActivate : false,
38794     
38795     activeClass : "x-menu-item-active",
38796     
38797     hideOnClick : true,
38798     
38799     clickHideDelay : 1,
38800
38801     
38802     ctype : "Ext.menu.BaseItem",
38803
38804     
38805     actionMode : "container",
38806
38807     initComponent : function(){
38808         Ext.menu.BaseItem.superclass.initComponent.call(this);
38809         this.addEvents(
38810             
38811             'click',
38812             
38813             'activate',
38814             
38815             'deactivate'
38816         );
38817         if(this.handler){
38818             this.on("click", this.handler, this.scope);
38819         }
38820     },
38821
38822     
38823     onRender : function(container, position){
38824         Ext.menu.BaseItem.superclass.onRender.apply(this, arguments);
38825         if(this.ownerCt && this.ownerCt instanceof Ext.menu.Menu){
38826             this.parentMenu = this.ownerCt;
38827         }else{
38828             this.container.addClass('x-menu-list-item');
38829             this.mon(this.el, {
38830                 scope: this,
38831                 click: this.onClick,
38832                 mouseenter: this.activate,
38833                 mouseleave: this.deactivate
38834             });
38835         }
38836     },
38837
38838     
38839     setHandler : function(handler, scope){
38840         if(this.handler){
38841             this.un("click", this.handler, this.scope);
38842         }
38843         this.on("click", this.handler = handler, this.scope = scope);
38844     },
38845
38846     
38847     onClick : function(e){
38848         if(!this.disabled && this.fireEvent("click", this, e) !== false
38849                 && (this.parentMenu && this.parentMenu.fireEvent("itemclick", this, e) !== false)){
38850             this.handleClick(e);
38851         }else{
38852             e.stopEvent();
38853         }
38854     },
38855
38856     
38857     activate : function(){
38858         if(this.disabled){
38859             return false;
38860         }
38861         var li = this.container;
38862         li.addClass(this.activeClass);
38863         this.region = li.getRegion().adjust(2, 2, -2, -2);
38864         this.fireEvent("activate", this);
38865         return true;
38866     },
38867
38868     
38869     deactivate : function(){
38870         this.container.removeClass(this.activeClass);
38871         this.fireEvent("deactivate", this);
38872     },
38873
38874     
38875     shouldDeactivate : function(e){
38876         return !this.region || !this.region.contains(e.getPoint());
38877     },
38878
38879     
38880     handleClick : function(e){
38881         var pm = this.parentMenu;
38882         if(this.hideOnClick){
38883             if(pm.floating){
38884                 pm.hide.defer(this.clickHideDelay, pm, [true]);
38885             }else{
38886                 pm.deactivateActive();
38887             }
38888         }
38889     },
38890
38891     
38892     expandMenu : Ext.emptyFn,
38893
38894     
38895     hideMenu : Ext.emptyFn
38896 });
38897 Ext.reg('menubaseitem', Ext.menu.BaseItem);
38898 Ext.menu.TextItem = Ext.extend(Ext.menu.BaseItem, {
38899     
38900     
38901     hideOnClick : false,
38902     
38903     itemCls : "x-menu-text",
38904     
38905     constructor : function(config) {
38906         if (typeof config == 'string') {
38907             config = {
38908                 text: config
38909             };
38910         }
38911         Ext.menu.TextItem.superclass.constructor.call(this, config);
38912     },
38913
38914     
38915     onRender : function() {
38916         var s = document.createElement("span");
38917         s.className = this.itemCls;
38918         s.innerHTML = this.text;
38919         this.el = s;
38920         Ext.menu.TextItem.superclass.onRender.apply(this, arguments);
38921     }
38922 });
38923 Ext.reg('menutextitem', Ext.menu.TextItem);
38924 Ext.menu.Separator = Ext.extend(Ext.menu.BaseItem, {
38925     
38926     itemCls : "x-menu-sep",
38927     
38928     hideOnClick : false,
38929     
38930     
38931     activeClass: '',
38932
38933     
38934     onRender : function(li){
38935         var s = document.createElement("span");
38936         s.className = this.itemCls;
38937         s.innerHTML = "&#160;";
38938         this.el = s;
38939         li.addClass("x-menu-sep-li");
38940         Ext.menu.Separator.superclass.onRender.apply(this, arguments);
38941     }
38942 });
38943 Ext.reg('menuseparator', Ext.menu.Separator);
38944 Ext.menu.Item = Ext.extend(Ext.menu.BaseItem, {
38945     
38946     
38947     
38948     
38949     
38950     
38951     
38952     
38953     itemCls : 'x-menu-item',
38954     
38955     canActivate : true,
38956     
38957     showDelay: 200,
38958     
38959     
38960     altText: '',
38961     
38962     
38963     hideDelay: 200,
38964
38965     
38966     ctype: 'Ext.menu.Item',
38967
38968     initComponent : function(){
38969         Ext.menu.Item.superclass.initComponent.call(this);
38970         if(this.menu){
38971             this.menu = Ext.menu.MenuMgr.get(this.menu);
38972             this.menu.ownerCt = this;
38973         }
38974     },
38975
38976     
38977     onRender : function(container, position){
38978         if (!this.itemTpl) {
38979             this.itemTpl = Ext.menu.Item.prototype.itemTpl = new Ext.XTemplate(
38980                 '<a id="{id}" class="{cls}" hidefocus="true" unselectable="on" href="{href}"',
38981                     '<tpl if="hrefTarget">',
38982                         ' target="{hrefTarget}"',
38983                     '</tpl>',
38984                  '>',
38985                      '<img alt="{altText}" src="{icon}" class="x-menu-item-icon {iconCls}"/>',
38986                      '<span class="x-menu-item-text">{text}</span>',
38987                  '</a>'
38988              );
38989         }
38990         var a = this.getTemplateArgs();
38991         this.el = position ? this.itemTpl.insertBefore(position, a, true) : this.itemTpl.append(container, a, true);
38992         this.iconEl = this.el.child('img.x-menu-item-icon');
38993         this.textEl = this.el.child('.x-menu-item-text');
38994         if(!this.href) { 
38995             this.mon(this.el, 'click', Ext.emptyFn, null, { preventDefault: true });
38996         }
38997         Ext.menu.Item.superclass.onRender.call(this, container, position);
38998     },
38999
39000     getTemplateArgs: function() {
39001         return {
39002             id: this.id,
39003             cls: this.itemCls + (this.menu ?  ' x-menu-item-arrow' : '') + (this.cls ?  ' ' + this.cls : ''),
39004             href: this.href || '#',
39005             hrefTarget: this.hrefTarget,
39006             icon: this.icon || Ext.BLANK_IMAGE_URL,
39007             iconCls: this.iconCls || '',
39008             text: this.itemText||this.text||'&#160;',
39009             altText: this.altText || ''
39010         };
39011     },
39012
39013     
39014     setText : function(text){
39015         this.text = text||'&#160;';
39016         if(this.rendered){
39017             this.textEl.update(this.text);
39018             this.parentMenu.layout.doAutoSize();
39019         }
39020     },
39021
39022     
39023     setIconClass : function(cls){
39024         var oldCls = this.iconCls;
39025         this.iconCls = cls;
39026         if(this.rendered){
39027             this.iconEl.replaceClass(oldCls, this.iconCls);
39028         }
39029     },
39030
39031     
39032     beforeDestroy: function(){
39033         if (this.menu){
39034             delete this.menu.ownerCt;
39035             this.menu.destroy();
39036         }
39037         Ext.menu.Item.superclass.beforeDestroy.call(this);
39038     },
39039
39040     
39041     handleClick : function(e){
39042         if(!this.href){ 
39043             e.stopEvent();
39044         }
39045         Ext.menu.Item.superclass.handleClick.apply(this, arguments);
39046     },
39047
39048     
39049     activate : function(autoExpand){
39050         if(Ext.menu.Item.superclass.activate.apply(this, arguments)){
39051             this.focus();
39052             if(autoExpand){
39053                 this.expandMenu();
39054             }
39055         }
39056         return true;
39057     },
39058
39059     
39060     shouldDeactivate : function(e){
39061         if(Ext.menu.Item.superclass.shouldDeactivate.call(this, e)){
39062             if(this.menu && this.menu.isVisible()){
39063                 return !this.menu.getEl().getRegion().contains(e.getPoint());
39064             }
39065             return true;
39066         }
39067         return false;
39068     },
39069
39070     
39071     deactivate : function(){
39072         Ext.menu.Item.superclass.deactivate.apply(this, arguments);
39073         this.hideMenu();
39074     },
39075
39076     
39077     expandMenu : function(autoActivate){
39078         if(!this.disabled && this.menu){
39079             clearTimeout(this.hideTimer);
39080             delete this.hideTimer;
39081             if(!this.menu.isVisible() && !this.showTimer){
39082                 this.showTimer = this.deferExpand.defer(this.showDelay, this, [autoActivate]);
39083             }else if (this.menu.isVisible() && autoActivate){
39084                 this.menu.tryActivate(0, 1);
39085             }
39086         }
39087     },
39088
39089     
39090     deferExpand : function(autoActivate){
39091         delete this.showTimer;
39092         this.menu.show(this.container, this.parentMenu.subMenuAlign || 'tl-tr?', this.parentMenu);
39093         if(autoActivate){
39094             this.menu.tryActivate(0, 1);
39095         }
39096     },
39097
39098     
39099     hideMenu : function(){
39100         clearTimeout(this.showTimer);
39101         delete this.showTimer;
39102         if(!this.hideTimer && this.menu && this.menu.isVisible()){
39103             this.hideTimer = this.deferHide.defer(this.hideDelay, this);
39104         }
39105     },
39106
39107     
39108     deferHide : function(){
39109         delete this.hideTimer;
39110         if(this.menu.over){
39111             this.parentMenu.setActiveItem(this, false);
39112         }else{
39113             this.menu.hide();
39114         }
39115     }
39116 });
39117 Ext.reg('menuitem', Ext.menu.Item);
39118 Ext.menu.CheckItem = Ext.extend(Ext.menu.Item, {
39119     
39120     
39121     itemCls : "x-menu-item x-menu-check-item",
39122     
39123     groupClass : "x-menu-group-item",
39124
39125     
39126     checked: false,
39127
39128     
39129     ctype: "Ext.menu.CheckItem",
39130     
39131     initComponent : function(){
39132         Ext.menu.CheckItem.superclass.initComponent.call(this);
39133             this.addEvents(
39134                 
39135                 "beforecheckchange" ,
39136                 
39137                 "checkchange"
39138             );
39139             
39140             if(this.checkHandler){
39141                 this.on('checkchange', this.checkHandler, this.scope);
39142             }
39143             Ext.menu.MenuMgr.registerCheckable(this);
39144     },
39145
39146     
39147     onRender : function(c){
39148         Ext.menu.CheckItem.superclass.onRender.apply(this, arguments);
39149         if(this.group){
39150             this.el.addClass(this.groupClass);
39151         }
39152         if(this.checked){
39153             this.checked = false;
39154             this.setChecked(true, true);
39155         }
39156     },
39157
39158     
39159     destroy : function(){
39160         Ext.menu.MenuMgr.unregisterCheckable(this);
39161         Ext.menu.CheckItem.superclass.destroy.apply(this, arguments);
39162     },
39163
39164     
39165     setChecked : function(state, suppressEvent){
39166         var suppress = suppressEvent === true;
39167         if(this.checked != state && (suppress || this.fireEvent("beforecheckchange", this, state) !== false)){
39168             Ext.menu.MenuMgr.onCheckChange(this, state);
39169             if(this.container){
39170                 this.container[state ? "addClass" : "removeClass"]("x-menu-item-checked");
39171             }
39172             this.checked = state;
39173             if(!suppress){
39174                 this.fireEvent("checkchange", this, state);
39175             }
39176         }
39177     },
39178
39179     
39180     handleClick : function(e){
39181        if(!this.disabled && !(this.checked && this.group)){
39182            this.setChecked(!this.checked);
39183        }
39184        Ext.menu.CheckItem.superclass.handleClick.apply(this, arguments);
39185     }
39186 });
39187 Ext.reg('menucheckitem', Ext.menu.CheckItem);
39188  Ext.menu.DateMenu = Ext.extend(Ext.menu.Menu, {
39189     
39190     enableScrolling : false,
39191     
39192         
39193     
39194     hideOnClick : true,
39195     
39196     
39197     pickerId : null,
39198     
39199     
39200     
39201     
39202     cls : 'x-date-menu',
39203     
39204     
39205     
39206     
39207
39208     initComponent : function(){
39209         this.on('beforeshow', this.onBeforeShow, this);
39210         if(this.strict = (Ext.isIE7 && Ext.isStrict)){
39211             this.on('show', this.onShow, this, {single: true, delay: 20});
39212         }
39213         Ext.apply(this, {
39214             plain: true,
39215             showSeparator: false,
39216             items: this.picker = new Ext.DatePicker(Ext.applyIf({
39217                 internalRender: this.strict || !Ext.isIE,
39218                 ctCls: 'x-menu-date-item',
39219                 id: this.pickerId
39220             }, this.initialConfig))
39221         });
39222         this.picker.purgeListeners();
39223         Ext.menu.DateMenu.superclass.initComponent.call(this);
39224         
39225         this.relayEvents(this.picker, ['select']);
39226         this.on('show', this.picker.focus, this.picker);
39227         this.on('select', this.menuHide, this);
39228         if(this.handler){
39229             this.on('select', this.handler, this.scope || this);
39230         }
39231     },
39232
39233     menuHide : function() {
39234         if(this.hideOnClick){
39235             this.hide(true);
39236         }
39237     },
39238
39239     onBeforeShow : function(){
39240         if(this.picker){
39241             this.picker.hideMonthPicker(true);
39242         }
39243     },
39244
39245     onShow : function(){
39246         var el = this.picker.getEl();
39247         el.setWidth(el.getWidth()); 
39248     }
39249  });
39250  Ext.reg('datemenu', Ext.menu.DateMenu);
39251  
39252  Ext.menu.ColorMenu = Ext.extend(Ext.menu.Menu, {
39253     
39254     enableScrolling : false,
39255     
39256         
39257     
39258     
39259     hideOnClick : true,
39260     
39261     cls : 'x-color-menu',
39262     
39263     
39264     paletteId : null,
39265     
39266     
39267     
39268     
39269     
39270     
39271     
39272     
39273     
39274     
39275     initComponent : function(){
39276         Ext.apply(this, {
39277             plain: true,
39278             showSeparator: false,
39279             items: this.palette = new Ext.ColorPalette(Ext.applyIf({
39280                 id: this.paletteId
39281             }, this.initialConfig))
39282         });
39283         this.palette.purgeListeners();
39284         Ext.menu.ColorMenu.superclass.initComponent.call(this);
39285         
39286         this.relayEvents(this.palette, ['select']);
39287         this.on('select', this.menuHide, this);
39288         if(this.handler){
39289             this.on('select', this.handler, this.scope || this);
39290         }
39291     },
39292
39293     menuHide : function(){
39294         if(this.hideOnClick){
39295             this.hide(true);
39296         }
39297     }
39298 });
39299 Ext.reg('colormenu', Ext.menu.ColorMenu);
39300
39301 Ext.form.Field = Ext.extend(Ext.BoxComponent,  {
39302     
39303     
39304     
39305     
39306     
39307     
39308
39309     
39310     invalidClass : 'x-form-invalid',
39311     
39312     invalidText : 'The value in this field is invalid',
39313     
39314     focusClass : 'x-form-focus',
39315     
39316     
39317     validationEvent : 'keyup',
39318     
39319     validateOnBlur : true,
39320     
39321     validationDelay : 250,
39322     
39323     defaultAutoCreate : {tag: 'input', type: 'text', size: '20', autocomplete: 'off'},
39324     
39325     fieldClass : 'x-form-field',
39326     
39327     msgTarget : 'qtip',
39328     
39329     msgFx : 'normal',
39330     
39331     readOnly : false,
39332     
39333     disabled : false,
39334     
39335     submitValue: true,
39336
39337     
39338     isFormField : true,
39339
39340     
39341     msgDisplay: '',
39342
39343     
39344     hasFocus : false,
39345
39346     
39347     initComponent : function(){
39348         Ext.form.Field.superclass.initComponent.call(this);
39349         this.addEvents(
39350             
39351             'focus',
39352             
39353             'blur',
39354             
39355             'specialkey',
39356             
39357             'change',
39358             
39359             'invalid',
39360             
39361             'valid'
39362         );
39363     },
39364
39365     
39366     getName : function(){
39367         return this.rendered && this.el.dom.name ? this.el.dom.name : this.name || this.id || '';
39368     },
39369
39370     
39371     onRender : function(ct, position){
39372         if(!this.el){
39373             var cfg = this.getAutoCreate();
39374
39375             if(!cfg.name){
39376                 cfg.name = this.name || this.id;
39377             }
39378             if(this.inputType){
39379                 cfg.type = this.inputType;
39380             }
39381             this.autoEl = cfg;
39382         }
39383         Ext.form.Field.superclass.onRender.call(this, ct, position);
39384         if(this.submitValue === false){
39385             this.el.dom.removeAttribute('name');
39386         }
39387         var type = this.el.dom.type;
39388         if(type){
39389             if(type == 'password'){
39390                 type = 'text';
39391             }
39392             this.el.addClass('x-form-'+type);
39393         }
39394         if(this.readOnly){
39395             this.setReadOnly(true);
39396         }
39397         if(this.tabIndex !== undefined){
39398             this.el.dom.setAttribute('tabIndex', this.tabIndex);
39399         }
39400
39401         this.el.addClass([this.fieldClass, this.cls]);
39402     },
39403
39404     
39405     getItemCt : function(){
39406         return this.itemCt;
39407     },
39408
39409     
39410     initValue : function(){
39411         if(this.value !== undefined){
39412             this.setValue(this.value);
39413         }else if(!Ext.isEmpty(this.el.dom.value) && this.el.dom.value != this.emptyText){
39414             this.setValue(this.el.dom.value);
39415         }
39416         
39417         this.originalValue = this.getValue();
39418     },
39419
39420     
39421     isDirty : function() {
39422         if(this.disabled || !this.rendered) {
39423             return false;
39424         }
39425         return String(this.getValue()) !== String(this.originalValue);
39426     },
39427
39428     
39429     setReadOnly : function(readOnly){
39430         if(this.rendered){
39431             this.el.dom.readOnly = readOnly;
39432         }
39433         this.readOnly = readOnly;
39434     },
39435
39436     
39437     afterRender : function(){
39438         Ext.form.Field.superclass.afterRender.call(this);
39439         this.initEvents();
39440         this.initValue();
39441     },
39442
39443     
39444     fireKey : function(e){
39445         if(e.isSpecialKey()){
39446             this.fireEvent('specialkey', this, e);
39447         }
39448     },
39449
39450     
39451     reset : function(){
39452         this.setValue(this.originalValue);
39453         this.clearInvalid();
39454     },
39455
39456     
39457     initEvents : function(){
39458         this.mon(this.el, Ext.EventManager.getKeyEvent(), this.fireKey,  this);
39459         this.mon(this.el, 'focus', this.onFocus, this);
39460
39461         
39462         
39463         this.mon(this.el, 'blur', this.onBlur, this, this.inEditor ? {buffer:10} : null);
39464     },
39465
39466     
39467     preFocus: Ext.emptyFn,
39468
39469     
39470     onFocus : function(){
39471         this.preFocus();
39472         if(this.focusClass){
39473             this.el.addClass(this.focusClass);
39474         }
39475         if(!this.hasFocus){
39476             this.hasFocus = true;
39477             
39478             this.startValue = this.getValue();
39479             this.fireEvent('focus', this);
39480         }
39481     },
39482
39483     
39484     beforeBlur : Ext.emptyFn,
39485
39486     
39487     onBlur : function(){
39488         this.beforeBlur();
39489         if(this.focusClass){
39490             this.el.removeClass(this.focusClass);
39491         }
39492         this.hasFocus = false;
39493         if(this.validationEvent !== false && (this.validateOnBlur || this.validationEvent == 'blur')){
39494             this.validate();
39495         }
39496         var v = this.getValue();
39497         if(String(v) !== String(this.startValue)){
39498             this.fireEvent('change', this, v, this.startValue);
39499         }
39500         this.fireEvent('blur', this);
39501         this.postBlur();
39502     },
39503
39504     
39505     postBlur : Ext.emptyFn,
39506
39507     
39508     isValid : function(preventMark){
39509         if(this.disabled){
39510             return true;
39511         }
39512         var restore = this.preventMark;
39513         this.preventMark = preventMark === true;
39514         var v = this.validateValue(this.processValue(this.getRawValue()));
39515         this.preventMark = restore;
39516         return v;
39517     },
39518
39519     
39520     validate : function(){
39521         if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
39522             this.clearInvalid();
39523             return true;
39524         }
39525         return false;
39526     },
39527
39528     
39529     processValue : function(value){
39530         return value;
39531     },
39532
39533     
39534      validateValue : function(value) {
39535          
39536          var error = this.getErrors(value)[0];
39537
39538          if (error == undefined) {
39539              return true;
39540          } else {
39541              this.markInvalid(error);
39542              return false;
39543          }
39544      },
39545     
39546     
39547     getErrors: function() {
39548         return [];
39549     },
39550
39551     
39552     getActiveError : function(){
39553         return this.activeError || '';
39554     },
39555
39556     
39557     markInvalid : function(msg){
39558         
39559         if (this.rendered && !this.preventMark) {
39560             msg = msg || this.invalidText;
39561
39562             var mt = this.getMessageHandler();
39563             if(mt){
39564                 mt.mark(this, msg);
39565             }else if(this.msgTarget){
39566                 this.el.addClass(this.invalidClass);
39567                 var t = Ext.getDom(this.msgTarget);
39568                 if(t){
39569                     t.innerHTML = msg;
39570                     t.style.display = this.msgDisplay;
39571                 }
39572             }
39573         }
39574         
39575         this.setActiveError(msg);
39576     },
39577     
39578     
39579     clearInvalid : function(){
39580         
39581         if (this.rendered && !this.preventMark) {
39582             this.el.removeClass(this.invalidClass);
39583             var mt = this.getMessageHandler();
39584             if(mt){
39585                 mt.clear(this);
39586             }else if(this.msgTarget){
39587                 this.el.removeClass(this.invalidClass);
39588                 var t = Ext.getDom(this.msgTarget);
39589                 if(t){
39590                     t.innerHTML = '';
39591                     t.style.display = 'none';
39592                 }
39593             }
39594         }
39595         
39596         this.unsetActiveError();
39597     },
39598
39599     
39600     setActiveError: function(msg, suppressEvent) {
39601         this.activeError = msg;
39602         if (suppressEvent !== true) this.fireEvent('invalid', this, msg);
39603     },
39604     
39605     
39606     unsetActiveError: function(suppressEvent) {
39607         delete this.activeError;
39608         if (suppressEvent !== true) this.fireEvent('valid', this);
39609     },
39610
39611     
39612     getMessageHandler : function(){
39613         return Ext.form.MessageTargets[this.msgTarget];
39614     },
39615
39616     
39617     getErrorCt : function(){
39618         return this.el.findParent('.x-form-element', 5, true) || 
39619             this.el.findParent('.x-form-field-wrap', 5, true);   
39620     },
39621
39622     
39623     alignErrorEl : function(){
39624         this.errorEl.setWidth(this.getErrorCt().getWidth(true) - 20);
39625     },
39626
39627     
39628     alignErrorIcon : function(){
39629         this.errorIcon.alignTo(this.el, 'tl-tr', [2, 0]);
39630     },
39631
39632     
39633     getRawValue : function(){
39634         var v = this.rendered ? this.el.getValue() : Ext.value(this.value, '');
39635         if(v === this.emptyText){
39636             v = '';
39637         }
39638         return v;
39639     },
39640
39641     
39642     getValue : function(){
39643         if(!this.rendered) {
39644             return this.value;
39645         }
39646         var v = this.el.getValue();
39647         if(v === this.emptyText || v === undefined){
39648             v = '';
39649         }
39650         return v;
39651     },
39652
39653     
39654     setRawValue : function(v){
39655         return this.rendered ? (this.el.dom.value = (Ext.isEmpty(v) ? '' : v)) : '';
39656     },
39657
39658     
39659     setValue : function(v){
39660         this.value = v;
39661         if(this.rendered){
39662             this.el.dom.value = (Ext.isEmpty(v) ? '' : v);
39663             this.validate();
39664         }
39665         return this;
39666     },
39667
39668     
39669     append : function(v){
39670          this.setValue([this.getValue(), v].join(''));
39671     }
39672
39673     
39674     
39675
39676     
39677 });
39678
39679
39680 Ext.form.MessageTargets = {
39681     'qtip' : {
39682         mark: function(field, msg){
39683             field.el.addClass(field.invalidClass);
39684             field.el.dom.qtip = msg;
39685             field.el.dom.qclass = 'x-form-invalid-tip';
39686             if(Ext.QuickTips){ 
39687                 Ext.QuickTips.enable();
39688             }
39689         },
39690         clear: function(field){
39691             field.el.removeClass(field.invalidClass);
39692             field.el.dom.qtip = '';
39693         }
39694     },
39695     'title' : {
39696         mark: function(field, msg){
39697             field.el.addClass(field.invalidClass);
39698             field.el.dom.title = msg;
39699         },
39700         clear: function(field){
39701             field.el.dom.title = '';
39702         }
39703     },
39704     'under' : {
39705         mark: function(field, msg){
39706             field.el.addClass(field.invalidClass);
39707             if(!field.errorEl){
39708                 var elp = field.getErrorCt();
39709                 if(!elp){ 
39710                     field.el.dom.title = msg;
39711                     return;
39712                 }
39713                 field.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
39714                 field.on('resize', field.alignErrorEl, field);
39715                 field.on('destroy', function(){
39716                     Ext.destroy(this.errorEl);
39717                 }, field);
39718             }
39719             field.alignErrorEl();
39720             field.errorEl.update(msg);
39721             Ext.form.Field.msgFx[field.msgFx].show(field.errorEl, field);
39722         },
39723         clear: function(field){
39724             field.el.removeClass(field.invalidClass);
39725             if(field.errorEl){
39726                 Ext.form.Field.msgFx[field.msgFx].hide(field.errorEl, field);
39727             }else{
39728                 field.el.dom.title = '';
39729             }
39730         }
39731     },
39732     'side' : {
39733         mark: function(field, msg){
39734             field.el.addClass(field.invalidClass);
39735             if(!field.errorIcon){
39736                 var elp = field.getErrorCt();
39737                 
39738                 if(!elp){
39739                     field.el.dom.title = msg;
39740                     return;
39741                 }
39742                 field.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
39743                 if (field.ownerCt) {
39744                     field.ownerCt.on('afterlayout', field.alignErrorIcon, field);
39745                     field.ownerCt.on('expand', field.alignErrorIcon, field);
39746                 }
39747                 field.on('resize', field.alignErrorIcon, field);
39748                 field.on('destroy', function(){
39749                     Ext.destroy(this.errorIcon);
39750                 }, field);
39751             }
39752             field.alignErrorIcon();
39753             field.errorIcon.dom.qtip = msg;
39754             field.errorIcon.dom.qclass = 'x-form-invalid-tip';
39755             field.errorIcon.show();
39756         },
39757         clear: function(field){
39758             field.el.removeClass(field.invalidClass);
39759             if(field.errorIcon){
39760                 field.errorIcon.dom.qtip = '';
39761                 field.errorIcon.hide();
39762             }else{
39763                 field.el.dom.title = '';
39764             }
39765         }
39766     }
39767 };
39768
39769
39770 Ext.form.Field.msgFx = {
39771     normal : {
39772         show: function(msgEl, f){
39773             msgEl.setDisplayed('block');
39774         },
39775
39776         hide : function(msgEl, f){
39777             msgEl.setDisplayed(false).update('');
39778         }
39779     },
39780
39781     slide : {
39782         show: function(msgEl, f){
39783             msgEl.slideIn('t', {stopFx:true});
39784         },
39785
39786         hide : function(msgEl, f){
39787             msgEl.slideOut('t', {stopFx:true,useDisplay:true});
39788         }
39789     },
39790
39791     slideRight : {
39792         show: function(msgEl, f){
39793             msgEl.fixDisplay();
39794             msgEl.alignTo(f.el, 'tl-tr');
39795             msgEl.slideIn('l', {stopFx:true});
39796         },
39797
39798         hide : function(msgEl, f){
39799             msgEl.slideOut('l', {stopFx:true,useDisplay:true});
39800         }
39801     }
39802 };
39803 Ext.reg('field', Ext.form.Field);
39804
39805 Ext.form.TextField = Ext.extend(Ext.form.Field,  {
39806     
39807     
39808     
39809     grow : false,
39810     
39811     growMin : 30,
39812     
39813     growMax : 800,
39814     
39815     vtype : null,
39816     
39817     maskRe : null,
39818     
39819     disableKeyFilter : false,
39820     
39821     allowBlank : true,
39822     
39823     minLength : 0,
39824     
39825     maxLength : Number.MAX_VALUE,
39826     
39827     minLengthText : 'The minimum length for this field is {0}',
39828     
39829     maxLengthText : 'The maximum length for this field is {0}',
39830     
39831     selectOnFocus : false,
39832     
39833     blankText : 'This field is required',
39834     
39835     validator : null,
39836     
39837     regex : null,
39838     
39839     regexText : '',
39840     
39841     emptyText : null,
39842     
39843     emptyClass : 'x-form-empty-field',
39844
39845     
39846
39847     initComponent : function(){
39848         Ext.form.TextField.superclass.initComponent.call(this);
39849         this.addEvents(
39850             
39851             'autosize',
39852
39853             
39854             'keydown',
39855             
39856             'keyup',
39857             
39858             'keypress'
39859         );
39860     },
39861
39862     
39863     initEvents : function(){
39864         Ext.form.TextField.superclass.initEvents.call(this);
39865         if(this.validationEvent == 'keyup'){
39866             this.validationTask = new Ext.util.DelayedTask(this.validate, this);
39867             this.mon(this.el, 'keyup', this.filterValidation, this);
39868         }
39869         else if(this.validationEvent !== false && this.validationEvent != 'blur'){
39870                 this.mon(this.el, this.validationEvent, this.validate, this, {buffer: this.validationDelay});
39871         }
39872         if(this.selectOnFocus || this.emptyText){            
39873             this.mon(this.el, 'mousedown', this.onMouseDown, this);
39874             
39875             if(this.emptyText){
39876                 this.applyEmptyText();
39877             }
39878         }
39879         if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Ext.form.VTypes[this.vtype+'Mask']))){
39880                 this.mon(this.el, 'keypress', this.filterKeys, this);
39881         }
39882         if(this.grow){
39883                 this.mon(this.el, 'keyup', this.onKeyUpBuffered, this, {buffer: 50});
39884                         this.mon(this.el, 'click', this.autoSize, this);
39885         }
39886         if(this.enableKeyEvents){
39887             this.mon(this.el, {
39888                 scope: this,
39889                 keyup: this.onKeyUp,
39890                 keydown: this.onKeyDown,
39891                 keypress: this.onKeyPress
39892             });
39893         }
39894     },
39895     
39896     onMouseDown: function(e){
39897         if(!this.hasFocus){
39898             this.mon(this.el, 'mouseup', Ext.emptyFn, this, { single: true, preventDefault: true });
39899         }
39900     },
39901
39902     processValue : function(value){
39903         if(this.stripCharsRe){
39904             var newValue = value.replace(this.stripCharsRe, '');
39905             if(newValue !== value){
39906                 this.setRawValue(newValue);
39907                 return newValue;
39908             }
39909         }
39910         return value;
39911     },
39912
39913     filterValidation : function(e){
39914         if(!e.isNavKeyPress()){
39915             this.validationTask.delay(this.validationDelay);
39916         }
39917     },
39918     
39919     
39920     onDisable: function(){
39921         Ext.form.TextField.superclass.onDisable.call(this);
39922         if(Ext.isIE){
39923             this.el.dom.unselectable = 'on';
39924         }
39925     },
39926     
39927     
39928     onEnable: function(){
39929         Ext.form.TextField.superclass.onEnable.call(this);
39930         if(Ext.isIE){
39931             this.el.dom.unselectable = '';
39932         }
39933     },
39934
39935     
39936     onKeyUpBuffered : function(e){
39937         if(this.doAutoSize(e)){
39938             this.autoSize();
39939         }
39940     },
39941     
39942     
39943     doAutoSize : function(e){
39944         return !e.isNavKeyPress();
39945     },
39946
39947     
39948     onKeyUp : function(e){
39949         this.fireEvent('keyup', this, e);
39950     },
39951
39952     
39953     onKeyDown : function(e){
39954         this.fireEvent('keydown', this, e);
39955     },
39956
39957     
39958     onKeyPress : function(e){
39959         this.fireEvent('keypress', this, e);
39960     },
39961
39962     
39963     reset : function(){
39964         Ext.form.TextField.superclass.reset.call(this);
39965         this.applyEmptyText();
39966     },
39967
39968     applyEmptyText : function(){
39969         if(this.rendered && this.emptyText && this.getRawValue().length < 1 && !this.hasFocus){
39970             this.setRawValue(this.emptyText);
39971             this.el.addClass(this.emptyClass);
39972         }
39973     },
39974
39975     
39976     preFocus : function(){
39977         var el = this.el,
39978             isEmpty;
39979         if(this.emptyText){
39980             if(el.dom.value == this.emptyText){
39981                 this.setRawValue('');
39982                 isEmpty = true;
39983             }
39984             el.removeClass(this.emptyClass);
39985         }
39986         if(this.selectOnFocus || isEmpty){
39987             el.dom.select();
39988         }
39989     },
39990
39991     
39992     postBlur : function(){
39993         this.applyEmptyText();
39994     },
39995
39996     
39997     filterKeys : function(e){
39998         if(e.ctrlKey){
39999             return;
40000         }
40001         var k = e.getKey();
40002         if(Ext.isGecko && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
40003             return;
40004         }
40005         var cc = String.fromCharCode(e.getCharCode());
40006         if(!Ext.isGecko && e.isSpecialKey() && !cc){
40007             return;
40008         }
40009         if(!this.maskRe.test(cc)){
40010             e.stopEvent();
40011         }
40012     },
40013
40014     setValue : function(v){
40015         if(this.emptyText && this.el && !Ext.isEmpty(v)){
40016             this.el.removeClass(this.emptyClass);
40017         }
40018         Ext.form.TextField.superclass.setValue.apply(this, arguments);
40019         this.applyEmptyText();
40020         this.autoSize();
40021         return this;
40022     },
40023
40024     
40025     getErrors: function(value) {
40026         var errors = Ext.form.TextField.superclass.getErrors.apply(this, arguments);
40027         
40028         value = Ext.isDefined(value) ? value : this.processValue(this.getRawValue());        
40029         
40030         if (Ext.isFunction(this.validator)) {
40031             var msg = this.validator(value);
40032             if (msg !== true) {
40033                 errors.push(msg);
40034             }
40035         }
40036         
40037         if (value.length < 1 || value === this.emptyText) {
40038             if (this.allowBlank) {
40039                 
40040                 return errors;
40041             } else {
40042                 errors.push(this.blankText);
40043             }
40044         }
40045         
40046         if (!this.allowBlank && (value.length < 1 || value === this.emptyText)) { 
40047             errors.push(this.blankText);
40048         }
40049         
40050         if (value.length < this.minLength) {
40051             errors.push(String.format(this.minLengthText, this.minLength));
40052         }
40053         
40054         if (value.length > this.maxLength) {
40055             errors.push(String.format(this.maxLengthText, this.maxLength));
40056         }
40057         
40058         if (this.vtype) {
40059             var vt = Ext.form.VTypes;
40060             if(!vt[this.vtype](value, this)){
40061                 errors.push(this.vtypeText || vt[this.vtype +'Text']);
40062             }
40063         }
40064         
40065         if (this.regex && !this.regex.test(value)) {
40066             errors.push(this.regexText);
40067         }
40068         
40069         return errors;
40070     },
40071
40072     
40073     selectText : function(start, end){
40074         var v = this.getRawValue();
40075         var doFocus = false;
40076         if(v.length > 0){
40077             start = start === undefined ? 0 : start;
40078             end = end === undefined ? v.length : end;
40079             var d = this.el.dom;
40080             if(d.setSelectionRange){
40081                 d.setSelectionRange(start, end);
40082             }else if(d.createTextRange){
40083                 var range = d.createTextRange();
40084                 range.moveStart('character', start);
40085                 range.moveEnd('character', end-v.length);
40086                 range.select();
40087             }
40088             doFocus = Ext.isGecko || Ext.isOpera;
40089         }else{
40090             doFocus = true;
40091         }
40092         if(doFocus){
40093             this.focus();
40094         }
40095     },
40096
40097     
40098     autoSize : function(){
40099         if(!this.grow || !this.rendered){
40100             return;
40101         }
40102         if(!this.metrics){
40103             this.metrics = Ext.util.TextMetrics.createInstance(this.el);
40104         }
40105         var el = this.el;
40106         var v = el.dom.value;
40107         var d = document.createElement('div');
40108         d.appendChild(document.createTextNode(v));
40109         v = d.innerHTML;
40110         Ext.removeNode(d);
40111         d = null;
40112         v += '&#160;';
40113         var w = Math.min(this.growMax, Math.max(this.metrics.getWidth(v) +  10, this.growMin));
40114         this.el.setWidth(w);
40115         this.fireEvent('autosize', this, w);
40116     },
40117         
40118         onDestroy: function(){
40119                 if(this.validationTask){
40120                         this.validationTask.cancel();
40121                         this.validationTask = null;
40122                 }
40123                 Ext.form.TextField.superclass.onDestroy.call(this);
40124         }
40125 });
40126 Ext.reg('textfield', Ext.form.TextField);
40127
40128 Ext.form.TriggerField = Ext.extend(Ext.form.TextField,  {
40129     
40130     
40131     
40132     defaultAutoCreate : {tag: "input", type: "text", size: "16", autocomplete: "off"},
40133     
40134     hideTrigger:false,
40135     
40136     editable: true,
40137     
40138     readOnly: false,
40139     
40140     wrapFocusClass: 'x-trigger-wrap-focus',
40141     
40142     autoSize: Ext.emptyFn,
40143     
40144     monitorTab : true,
40145     
40146     deferHeight : true,
40147     
40148     mimicing : false,
40149
40150     actionMode: 'wrap',
40151
40152     defaultTriggerWidth: 17,
40153
40154     
40155     onResize : function(w, h){
40156         Ext.form.TriggerField.superclass.onResize.call(this, w, h);
40157         var tw = this.getTriggerWidth();
40158         if(Ext.isNumber(w)){
40159             this.el.setWidth(w - tw);
40160         }
40161         this.wrap.setWidth(this.el.getWidth() + tw);
40162     },
40163
40164     getTriggerWidth: function(){
40165         var tw = this.trigger.getWidth();
40166         if(!this.hideTrigger && !this.readOnly && tw === 0){
40167             tw = this.defaultTriggerWidth;
40168         }
40169         return tw;
40170     },
40171
40172     
40173     alignErrorIcon : function(){
40174         if(this.wrap){
40175             this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
40176         }
40177     },
40178
40179     
40180     onRender : function(ct, position){
40181         this.doc = Ext.isIE ? Ext.getBody() : Ext.getDoc();
40182         Ext.form.TriggerField.superclass.onRender.call(this, ct, position);
40183
40184         this.wrap = this.el.wrap({cls: 'x-form-field-wrap x-form-field-trigger-wrap'});
40185         this.trigger = this.wrap.createChild(this.triggerConfig ||
40186                 {tag: "img", src: Ext.BLANK_IMAGE_URL, alt: "", cls: "x-form-trigger " + this.triggerClass});
40187         this.initTrigger();
40188         if(!this.width){
40189             this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
40190         }
40191         this.resizeEl = this.positionEl = this.wrap;
40192     },
40193
40194     getWidth: function() {
40195         return(this.el.getWidth() + this.trigger.getWidth());
40196     },
40197
40198     updateEditState: function(){
40199         if(this.rendered){
40200             if (this.readOnly) {
40201                 this.el.dom.readOnly = true;
40202                 this.el.addClass('x-trigger-noedit');
40203                 this.mun(this.el, 'click', this.onTriggerClick, this);
40204                 this.trigger.setDisplayed(false);
40205             } else {
40206                 if (!this.editable) {
40207                     this.el.dom.readOnly = true;
40208                     this.el.addClass('x-trigger-noedit');
40209                     this.mon(this.el, 'click', this.onTriggerClick, this);
40210                 } else {
40211                     this.el.dom.readOnly = false;
40212                     this.el.removeClass('x-trigger-noedit');
40213                     this.mun(this.el, 'click', this.onTriggerClick, this);
40214                 }
40215                 this.trigger.setDisplayed(!this.hideTrigger);
40216             }
40217             this.onResize(this.width || this.wrap.getWidth());
40218         }
40219     },
40220
40221     
40222     setHideTrigger: function(hideTrigger){
40223         if(hideTrigger != this.hideTrigger){
40224             this.hideTrigger = hideTrigger;
40225             this.updateEditState();
40226         }
40227     },
40228
40229     
40230     setEditable: function(editable){
40231         if(editable != this.editable){
40232             this.editable = editable;
40233             this.updateEditState();
40234         }
40235     },
40236
40237     
40238     setReadOnly: function(readOnly){
40239         if(readOnly != this.readOnly){
40240             this.readOnly = readOnly;
40241             this.updateEditState();
40242         }
40243     },
40244
40245     afterRender : function(){
40246         Ext.form.TriggerField.superclass.afterRender.call(this);
40247         this.updateEditState();
40248     },
40249
40250     
40251     initTrigger : function(){
40252         this.mon(this.trigger, 'click', this.onTriggerClick, this, {preventDefault:true});
40253         this.trigger.addClassOnOver('x-form-trigger-over');
40254         this.trigger.addClassOnClick('x-form-trigger-click');
40255     },
40256
40257     
40258     onDestroy : function(){
40259         Ext.destroy(this.trigger, this.wrap);
40260         if (this.mimicing){
40261             this.doc.un('mousedown', this.mimicBlur, this);
40262         }
40263         delete this.doc;
40264         Ext.form.TriggerField.superclass.onDestroy.call(this);
40265     },
40266
40267     
40268     onFocus : function(){
40269         Ext.form.TriggerField.superclass.onFocus.call(this);
40270         if(!this.mimicing){
40271             this.wrap.addClass(this.wrapFocusClass);
40272             this.mimicing = true;
40273             this.doc.on('mousedown', this.mimicBlur, this, {delay: 10});
40274             if(this.monitorTab){
40275                 this.on('specialkey', this.checkTab, this);
40276             }
40277         }
40278     },
40279
40280     
40281     checkTab : function(me, e){
40282         if(e.getKey() == e.TAB){
40283             this.triggerBlur();
40284         }
40285     },
40286
40287     
40288     onBlur : Ext.emptyFn,
40289
40290     
40291     mimicBlur : function(e){
40292         if(!this.isDestroyed && !this.wrap.contains(e.target) && this.validateBlur(e)){
40293             this.triggerBlur();
40294         }
40295     },
40296
40297     
40298     triggerBlur : function(){
40299         this.mimicing = false;
40300         this.doc.un('mousedown', this.mimicBlur, this);
40301         if(this.monitorTab && this.el){
40302             this.un('specialkey', this.checkTab, this);
40303         }
40304         Ext.form.TriggerField.superclass.onBlur.call(this);
40305         if(this.wrap){
40306             this.wrap.removeClass(this.wrapFocusClass);
40307         }
40308     },
40309
40310     beforeBlur : Ext.emptyFn,
40311
40312     
40313     
40314     validateBlur : function(e){
40315         return true;
40316     },
40317
40318     
40319     onTriggerClick : Ext.emptyFn
40320
40321     
40322     
40323     
40324 });
40325
40326
40327 Ext.form.TwinTriggerField = Ext.extend(Ext.form.TriggerField, {
40328     
40329     
40330     
40331
40332     initComponent : function(){
40333         Ext.form.TwinTriggerField.superclass.initComponent.call(this);
40334
40335         this.triggerConfig = {
40336             tag:'span', cls:'x-form-twin-triggers', cn:[
40337             {tag: "img", src: Ext.BLANK_IMAGE_URL, alt: "", cls: "x-form-trigger " + this.trigger1Class},
40338             {tag: "img", src: Ext.BLANK_IMAGE_URL, alt: "", cls: "x-form-trigger " + this.trigger2Class}
40339         ]};
40340     },
40341
40342     getTrigger : function(index){
40343         return this.triggers[index];
40344     },
40345     
40346     afterRender: function(){
40347         Ext.form.TwinTriggerField.superclass.afterRender.call(this);
40348         var triggers = this.triggers,
40349             i = 0,
40350             len = triggers.length;
40351             
40352         for(; i < len; ++i){
40353             if(this['hideTrigger' + (i + 1)]){
40354                     triggers[i].hide();
40355                 }
40356
40357         }    
40358     },
40359
40360     initTrigger : function(){
40361         var ts = this.trigger.select('.x-form-trigger', true),
40362             triggerField = this;
40363             
40364         ts.each(function(t, all, index){
40365             var triggerIndex = 'Trigger'+(index+1);
40366             t.hide = function(){
40367                 var w = triggerField.wrap.getWidth();
40368                 this.dom.style.display = 'none';
40369                 triggerField.el.setWidth(w-triggerField.trigger.getWidth());
40370                 triggerField['hidden' + triggerIndex] = true;
40371             };
40372             t.show = function(){
40373                 var w = triggerField.wrap.getWidth();
40374                 this.dom.style.display = '';
40375                 triggerField.el.setWidth(w-triggerField.trigger.getWidth());
40376                 triggerField['hidden' + triggerIndex] = false;
40377             };
40378             this.mon(t, 'click', this['on'+triggerIndex+'Click'], this, {preventDefault:true});
40379             t.addClassOnOver('x-form-trigger-over');
40380             t.addClassOnClick('x-form-trigger-click');
40381         }, this);
40382         this.triggers = ts.elements;
40383     },
40384
40385     getTriggerWidth: function(){
40386         var tw = 0;
40387         Ext.each(this.triggers, function(t, index){
40388             var triggerIndex = 'Trigger' + (index + 1),
40389                 w = t.getWidth();
40390             if(w === 0 && !this['hidden' + triggerIndex]){
40391                 tw += this.defaultTriggerWidth;
40392             }else{
40393                 tw += w;
40394             }
40395         }, this);
40396         return tw;
40397     },
40398
40399     
40400     onDestroy : function() {
40401         Ext.destroy(this.triggers);
40402         Ext.form.TwinTriggerField.superclass.onDestroy.call(this);
40403     },
40404
40405     
40406     onTrigger1Click : Ext.emptyFn,
40407     
40408     onTrigger2Click : Ext.emptyFn
40409 });
40410 Ext.reg('trigger', Ext.form.TriggerField);
40411
40412 Ext.form.TextArea = Ext.extend(Ext.form.TextField,  {
40413     
40414     growMin : 60,
40415     
40416     growMax: 1000,
40417     growAppend : '&#160;\n&#160;',
40418
40419     enterIsSpecial : false,
40420
40421     
40422     preventScrollbars: false,
40423     
40424
40425     
40426     onRender : function(ct, position){
40427         if(!this.el){
40428             this.defaultAutoCreate = {
40429                 tag: "textarea",
40430                 style:"width:100px;height:60px;",
40431                 autocomplete: "off"
40432             };
40433         }
40434         Ext.form.TextArea.superclass.onRender.call(this, ct, position);
40435         if(this.grow){
40436             this.textSizeEl = Ext.DomHelper.append(document.body, {
40437                 tag: "pre", cls: "x-form-grow-sizer"
40438             });
40439             if(this.preventScrollbars){
40440                 this.el.setStyle("overflow", "hidden");
40441             }
40442             this.el.setHeight(this.growMin);
40443         }
40444     },
40445
40446     onDestroy : function(){
40447         Ext.removeNode(this.textSizeEl);
40448         Ext.form.TextArea.superclass.onDestroy.call(this);
40449     },
40450
40451     fireKey : function(e){
40452         if(e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() != e.ENTER || e.hasModifier()))){
40453             this.fireEvent("specialkey", this, e);
40454         }
40455     },
40456     
40457     
40458     doAutoSize : function(e){
40459         return !e.isNavKeyPress() || e.getKey() == e.ENTER;
40460     },
40461     
40462     
40463     filterValidation: function(e) {            
40464         if(!e.isNavKeyPress() || (!this.enterIsSpecial && e.keyCode == e.ENTER)){
40465             this.validationTask.delay(this.validationDelay);
40466         }
40467     },
40468
40469     
40470     autoSize: function(){
40471         if(!this.grow || !this.textSizeEl){
40472             return;
40473         }
40474         var el = this.el,
40475             v = Ext.util.Format.htmlEncode(el.dom.value),
40476             ts = this.textSizeEl,
40477             h;
40478             
40479         Ext.fly(ts).setWidth(this.el.getWidth());
40480         if(v.length < 1){
40481             v = "&#160;&#160;";
40482         }else{
40483             v += this.growAppend;
40484             if(Ext.isIE){
40485                 v = v.replace(/\n/g, '&#160;<br />');
40486             }
40487         }
40488         ts.innerHTML = v;
40489         h = Math.min(this.growMax, Math.max(ts.offsetHeight, this.growMin));
40490         if(h != this.lastHeight){
40491             this.lastHeight = h;
40492             this.el.setHeight(h);
40493             this.fireEvent("autosize", this, h);
40494         }
40495     }
40496 });
40497 Ext.reg('textarea', Ext.form.TextArea);
40498 Ext.form.NumberField = Ext.extend(Ext.form.TextField,  {
40499     
40500     
40501     
40502     fieldClass: "x-form-field x-form-num-field",
40503     
40504     
40505     allowDecimals : true,
40506     
40507     
40508     decimalSeparator : ".",
40509     
40510     
40511     decimalPrecision : 2,
40512     
40513     
40514     allowNegative : true,
40515     
40516     
40517     minValue : Number.NEGATIVE_INFINITY,
40518     
40519     
40520     maxValue : Number.MAX_VALUE,
40521     
40522     
40523     minText : "The minimum value for this field is {0}",
40524     
40525     
40526     maxText : "The maximum value for this field is {0}",
40527     
40528     
40529     nanText : "{0} is not a valid number",
40530     
40531     
40532     baseChars : "0123456789",
40533     
40534     
40535     autoStripChars: false,
40536
40537     
40538     initEvents : function() {
40539         var allowed = this.baseChars + '';
40540         if (this.allowDecimals) {
40541             allowed += this.decimalSeparator;
40542         }
40543         if (this.allowNegative) {
40544             allowed += '-';
40545         }
40546         allowed = Ext.escapeRe(allowed);
40547         this.maskRe = new RegExp('[' + allowed + ']');
40548         if (this.autoStripChars) {
40549             this.stripCharsRe = new RegExp('[^' + allowed + ']', 'gi');
40550         }
40551         
40552         Ext.form.NumberField.superclass.initEvents.call(this);
40553     },
40554     
40555     
40556     getErrors: function(value) {
40557         var errors = Ext.form.NumberField.superclass.getErrors.apply(this, arguments);
40558         
40559         value = Ext.isDefined(value) ? value : this.processValue(this.getRawValue());
40560         
40561         if (value.length < 1) { 
40562              return errors;
40563         }
40564         
40565         value = String(value).replace(this.decimalSeparator, ".");
40566         
40567         if(isNaN(value)){
40568             errors.push(String.format(this.nanText, value));
40569         }
40570         
40571         var num = this.parseValue(value);
40572         
40573         if (num < this.minValue) {
40574             errors.push(String.format(this.minText, this.minValue));
40575         }
40576         
40577         if (num > this.maxValue) {
40578             errors.push(String.format(this.maxText, this.maxValue));
40579         }
40580         
40581         return errors;
40582     },
40583
40584     getValue : function() {
40585         return this.fixPrecision(this.parseValue(Ext.form.NumberField.superclass.getValue.call(this)));
40586     },
40587
40588     setValue : function(v) {
40589         v = this.fixPrecision(v);
40590         v = Ext.isNumber(v) ? v : parseFloat(String(v).replace(this.decimalSeparator, "."));
40591         v = isNaN(v) ? '' : String(v).replace(".", this.decimalSeparator);
40592         return Ext.form.NumberField.superclass.setValue.call(this, v);
40593     },
40594     
40595     
40596     setMinValue : function(value) {
40597         this.minValue = Ext.num(value, Number.NEGATIVE_INFINITY);
40598     },
40599     
40600     
40601     setMaxValue : function(value) {
40602         this.maxValue = Ext.num(value, Number.MAX_VALUE);    
40603     },
40604
40605     
40606     parseValue : function(value) {
40607         value = parseFloat(String(value).replace(this.decimalSeparator, "."));
40608         return isNaN(value) ? '' : value;
40609     },
40610
40611     
40612     fixPrecision : function(value) {
40613         var nan = isNaN(value);
40614         
40615         if (!this.allowDecimals || this.decimalPrecision == -1 || nan || !value) {
40616             return nan ? '' : value;
40617         }
40618         
40619         return parseFloat(parseFloat(value).toFixed(this.decimalPrecision));
40620     },
40621
40622     beforeBlur : function() {
40623         var v = this.parseValue(this.getRawValue());
40624         
40625         if (!Ext.isEmpty(v)) {
40626             this.setValue(v);
40627         }
40628     }
40629 });
40630
40631 Ext.reg('numberfield', Ext.form.NumberField);
40632
40633 Ext.form.DateField = Ext.extend(Ext.form.TriggerField,  {
40634     
40635     format : "m/d/Y",
40636     
40637     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",
40638     
40639     disabledDaysText : "Disabled",
40640     
40641     disabledDatesText : "Disabled",
40642     
40643     minText : "The date in this field must be equal to or after {0}",
40644     
40645     maxText : "The date in this field must be equal to or before {0}",
40646     
40647     invalidText : "{0} is not a valid date - it must be in the format {1}",
40648     
40649     triggerClass : 'x-form-date-trigger',
40650     
40651     showToday : true,
40652     
40653     
40654     startDay : 0,
40655     
40656     
40657     
40658     
40659     
40660     
40661
40662     
40663     defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "off"},
40664
40665     
40666     
40667     initTime: '12', 
40668
40669     initTimeFormat: 'H',
40670
40671     
40672     safeParse : function(value, format) {
40673         if (/[gGhH]/.test(format.replace(/(\\.)/g, ''))) {
40674             
40675             return Date.parseDate(value, format);
40676         } else {
40677             
40678             var parsedDate = Date.parseDate(value + ' ' + this.initTime, format + ' ' + this.initTimeFormat);
40679
40680             if (parsedDate) {
40681                 return parsedDate.clearTime();
40682             }
40683         }
40684     },
40685
40686     initComponent : function(){
40687         Ext.form.DateField.superclass.initComponent.call(this);
40688
40689         this.addEvents(
40690             
40691             'select'
40692         );
40693
40694         if(Ext.isString(this.minValue)){
40695             this.minValue = this.parseDate(this.minValue);
40696         }
40697         if(Ext.isString(this.maxValue)){
40698             this.maxValue = this.parseDate(this.maxValue);
40699         }
40700         this.disabledDatesRE = null;
40701         this.initDisabledDays();
40702     },
40703
40704     initEvents: function() {
40705         Ext.form.DateField.superclass.initEvents.call(this);
40706         this.keyNav = new Ext.KeyNav(this.el, {
40707             "down": function(e) {
40708                 this.onTriggerClick();
40709             },
40710             scope: this,
40711             forceKeyDown: true
40712         });
40713     },
40714
40715
40716     
40717     initDisabledDays : function(){
40718         if(this.disabledDates){
40719             var dd = this.disabledDates,
40720                 len = dd.length - 1,
40721                 re = "(?:";
40722
40723             Ext.each(dd, function(d, i){
40724                 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
40725                 if(i != len){
40726                     re += '|';
40727                 }
40728             }, this);
40729             this.disabledDatesRE = new RegExp(re + ')');
40730         }
40731     },
40732
40733     
40734     setDisabledDates : function(dd){
40735         this.disabledDates = dd;
40736         this.initDisabledDays();
40737         if(this.menu){
40738             this.menu.picker.setDisabledDates(this.disabledDatesRE);
40739         }
40740     },
40741
40742     
40743     setDisabledDays : function(dd){
40744         this.disabledDays = dd;
40745         if(this.menu){
40746             this.menu.picker.setDisabledDays(dd);
40747         }
40748     },
40749
40750     
40751     setMinValue : function(dt){
40752         this.minValue = (Ext.isString(dt) ? this.parseDate(dt) : dt);
40753         if(this.menu){
40754             this.menu.picker.setMinDate(this.minValue);
40755         }
40756     },
40757
40758     
40759     setMaxValue : function(dt){
40760         this.maxValue = (Ext.isString(dt) ? this.parseDate(dt) : dt);
40761         if(this.menu){
40762             this.menu.picker.setMaxDate(this.maxValue);
40763         }
40764     },
40765
40766     
40767     getErrors: function(value) {
40768         var errors = Ext.form.DateField.superclass.getErrors.apply(this, arguments);
40769
40770         value = this.formatDate(value || this.processValue(this.getRawValue()));
40771
40772         if (value.length < 1) { 
40773              return errors;
40774         }
40775
40776         var svalue = value;
40777         value = this.parseDate(value);
40778         if (!value) {
40779             errors.push(String.format(this.invalidText, svalue, this.format));
40780             return errors;
40781         }
40782
40783         var time = value.getTime();
40784         if (this.minValue && time < this.minValue.clearTime().getTime()) {
40785             errors.push(String.format(this.minText, this.formatDate(this.minValue)));
40786         }
40787
40788         if (this.maxValue && time > this.maxValue.clearTime().getTime()) {
40789             errors.push(String.format(this.maxText, this.formatDate(this.maxValue)));
40790         }
40791
40792         if (this.disabledDays) {
40793             var day = value.getDay();
40794
40795             for(var i = 0; i < this.disabledDays.length; i++) {
40796                 if (day === this.disabledDays[i]) {
40797                     errors.push(this.disabledDaysText);
40798                     break;
40799                 }
40800             }
40801         }
40802
40803         var fvalue = this.formatDate(value);
40804         if (this.disabledDatesRE && this.disabledDatesRE.test(fvalue)) {
40805             errors.push(String.format(this.disabledDatesText, fvalue));
40806         }
40807
40808         return errors;
40809     },
40810
40811     
40812     
40813     validateBlur : function(){
40814         return !this.menu || !this.menu.isVisible();
40815     },
40816
40817     
40818     getValue : function(){
40819         return this.parseDate(Ext.form.DateField.superclass.getValue.call(this)) || "";
40820     },
40821
40822     
40823     setValue : function(date){
40824         return Ext.form.DateField.superclass.setValue.call(this, this.formatDate(this.parseDate(date)));
40825     },
40826
40827     
40828     parseDate : function(value) {
40829         if(!value || Ext.isDate(value)){
40830             return value;
40831         }
40832
40833         var v = this.safeParse(value, this.format),
40834             af = this.altFormats,
40835             afa = this.altFormatsArray;
40836
40837         if (!v && af) {
40838             afa = afa || af.split("|");
40839
40840             for (var i = 0, len = afa.length; i < len && !v; i++) {
40841                 v = this.safeParse(value, afa[i]);
40842             }
40843         }
40844         return v;
40845     },
40846
40847     
40848     onDestroy : function(){
40849         Ext.destroy(this.menu, this.keyNav);
40850         Ext.form.DateField.superclass.onDestroy.call(this);
40851     },
40852
40853     
40854     formatDate : function(date){
40855         return Ext.isDate(date) ? date.dateFormat(this.format) : date;
40856     },
40857
40858     
40859     
40860     
40861     onTriggerClick : function(){
40862         if(this.disabled){
40863             return;
40864         }
40865         if(this.menu == null){
40866             this.menu = new Ext.menu.DateMenu({
40867                 hideOnClick: false,
40868                 focusOnSelect: false
40869             });
40870         }
40871         this.onFocus();
40872         Ext.apply(this.menu.picker,  {
40873             minDate : this.minValue,
40874             maxDate : this.maxValue,
40875             disabledDatesRE : this.disabledDatesRE,
40876             disabledDatesText : this.disabledDatesText,
40877             disabledDays : this.disabledDays,
40878             disabledDaysText : this.disabledDaysText,
40879             format : this.format,
40880             showToday : this.showToday,
40881             startDay: this.startDay,
40882             minText : String.format(this.minText, this.formatDate(this.minValue)),
40883             maxText : String.format(this.maxText, this.formatDate(this.maxValue))
40884         });
40885         this.menu.picker.setValue(this.getValue() || new Date());
40886         this.menu.show(this.el, "tl-bl?");
40887         this.menuEvents('on');
40888     },
40889
40890     
40891     menuEvents: function(method){
40892         this.menu[method]('select', this.onSelect, this);
40893         this.menu[method]('hide', this.onMenuHide, this);
40894         this.menu[method]('show', this.onFocus, this);
40895     },
40896
40897     onSelect: function(m, d){
40898         this.setValue(d);
40899         this.fireEvent('select', this, d);
40900         this.menu.hide();
40901     },
40902
40903     onMenuHide: function(){
40904         this.focus(false, 60);
40905         this.menuEvents('un');
40906     },
40907
40908     
40909     beforeBlur : function(){
40910         var v = this.parseDate(this.getRawValue());
40911         if(v){
40912             this.setValue(v);
40913         }
40914     }
40915
40916     
40917     
40918     
40919     
40920 });
40921 Ext.reg('datefield', Ext.form.DateField);
40922
40923 Ext.form.DisplayField = Ext.extend(Ext.form.Field,  {
40924     validationEvent : false,
40925     validateOnBlur : false,
40926     defaultAutoCreate : {tag: "div"},
40927     
40928     fieldClass : "x-form-display-field",
40929     
40930     htmlEncode: false,
40931
40932     
40933     initEvents : Ext.emptyFn,
40934
40935     isValid : function(){
40936         return true;
40937     },
40938
40939     validate : function(){
40940         return true;
40941     },
40942
40943     getRawValue : function(){
40944         var v = this.rendered ? this.el.dom.innerHTML : Ext.value(this.value, '');
40945         if(v === this.emptyText){
40946             v = '';
40947         }
40948         if(this.htmlEncode){
40949             v = Ext.util.Format.htmlDecode(v);
40950         }
40951         return v;
40952     },
40953
40954     getValue : function(){
40955         return this.getRawValue();
40956     },
40957     
40958     getName: function() {
40959         return this.name;
40960     },
40961
40962     setRawValue : function(v){
40963         if(this.htmlEncode){
40964             v = Ext.util.Format.htmlEncode(v);
40965         }
40966         return this.rendered ? (this.el.dom.innerHTML = (Ext.isEmpty(v) ? '' : v)) : (this.value = v);
40967     },
40968
40969     setValue : function(v){
40970         this.setRawValue(v);
40971         return this;
40972     }
40973     
40974     
40975     
40976     
40977     
40978     
40979 });
40980
40981 Ext.reg('displayfield', Ext.form.DisplayField);
40982
40983 Ext.form.ComboBox = Ext.extend(Ext.form.TriggerField, {
40984     
40985     
40986     
40987     
40988     
40989
40990     
40991     defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},
40992     
40993     
40994     
40995     
40996     
40997     
40998     
40999     listClass : '',
41000     
41001     selectedClass : 'x-combo-selected',
41002     
41003     listEmptyText: '',
41004     
41005     triggerClass : 'x-form-arrow-trigger',
41006     
41007     shadow : 'sides',
41008     
41009     listAlign : 'tl-bl?',
41010     
41011     maxHeight : 300,
41012     
41013     minHeight : 90,
41014     
41015     triggerAction : 'query',
41016     
41017     minChars : 4,
41018     
41019     autoSelect : true,
41020     
41021     typeAhead : false,
41022     
41023     queryDelay : 500,
41024     
41025     pageSize : 0,
41026     
41027     selectOnFocus : false,
41028     
41029     queryParam : 'query',
41030     
41031     loadingText : 'Loading...',
41032     
41033     resizable : false,
41034     
41035     handleHeight : 8,
41036     
41037     allQuery: '',
41038     
41039     mode: 'remote',
41040     
41041     minListWidth : 70,
41042     
41043     forceSelection : false,
41044     
41045     typeAheadDelay : 250,
41046     
41047
41048     
41049     lazyInit : true,
41050
41051     
41052     clearFilterOnReset : true,
41053
41054     
41055     submitValue: undefined,
41056
41057     
41058
41059     
41060     initComponent : function(){
41061         Ext.form.ComboBox.superclass.initComponent.call(this);
41062         this.addEvents(
41063             
41064             'expand',
41065             
41066             'collapse',
41067
41068             
41069             'beforeselect',
41070             
41071             'select',
41072             
41073             'beforequery'
41074         );
41075         if(this.transform){
41076             var s = Ext.getDom(this.transform);
41077             if(!this.hiddenName){
41078                 this.hiddenName = s.name;
41079             }
41080             if(!this.store){
41081                 this.mode = 'local';
41082                 var d = [], opts = s.options;
41083                 for(var i = 0, len = opts.length;i < len; i++){
41084                     var o = opts[i],
41085                         value = (o.hasAttribute ? o.hasAttribute('value') : o.getAttributeNode('value').specified) ? o.value : o.text;
41086                     if(o.selected && Ext.isEmpty(this.value, true)) {
41087                         this.value = value;
41088                     }
41089                     d.push([value, o.text]);
41090                 }
41091                 this.store = new Ext.data.ArrayStore({
41092                     idIndex: 0,
41093                     fields: ['value', 'text'],
41094                     data : d,
41095                     autoDestroy: true
41096                 });
41097                 this.valueField = 'value';
41098                 this.displayField = 'text';
41099             }
41100             s.name = Ext.id(); 
41101             if(!this.lazyRender){
41102                 this.target = true;
41103                 this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);
41104                 this.render(this.el.parentNode, s);
41105             }
41106             Ext.removeNode(s);
41107         }
41108         
41109         else if(this.store){
41110             this.store = Ext.StoreMgr.lookup(this.store);
41111             if(this.store.autoCreated){
41112                 this.displayField = this.valueField = 'field1';
41113                 if(!this.store.expandData){
41114                     this.displayField = 'field2';
41115                 }
41116                 this.mode = 'local';
41117             }
41118         }
41119
41120         this.selectedIndex = -1;
41121         if(this.mode == 'local'){
41122             if(!Ext.isDefined(this.initialConfig.queryDelay)){
41123                 this.queryDelay = 10;
41124             }
41125             if(!Ext.isDefined(this.initialConfig.minChars)){
41126                 this.minChars = 0;
41127             }
41128         }
41129     },
41130
41131     
41132     onRender : function(ct, position){
41133         if(this.hiddenName && !Ext.isDefined(this.submitValue)){
41134             this.submitValue = false;
41135         }
41136         Ext.form.ComboBox.superclass.onRender.call(this, ct, position);
41137         if(this.hiddenName){
41138             this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName,
41139                     id: (this.hiddenId || Ext.id())}, 'before', true);
41140
41141         }
41142         if(Ext.isGecko){
41143             this.el.dom.setAttribute('autocomplete', 'off');
41144         }
41145
41146         if(!this.lazyInit){
41147             this.initList();
41148         }else{
41149             this.on('focus', this.initList, this, {single: true});
41150         }
41151     },
41152
41153     
41154     initValue : function(){
41155         Ext.form.ComboBox.superclass.initValue.call(this);
41156         if(this.hiddenField){
41157             this.hiddenField.value =
41158                 Ext.value(Ext.isDefined(this.hiddenValue) ? this.hiddenValue : this.value, '');
41159         }
41160     },
41161
41162     getParentZIndex : function(){
41163         var zindex;
41164         if (this.ownerCt){
41165             this.findParentBy(function(ct){
41166                 zindex = parseInt(ct.getPositionEl().getStyle('z-index'), 10);
41167                 return !!zindex;
41168             });
41169         }
41170         return zindex;
41171     },
41172     
41173     getZIndex : function(listParent){
41174         listParent = listParent || Ext.getDom(this.getListParent() || Ext.getBody());
41175         var zindex = parseInt(Ext.fly(listParent).getStyle('z-index'), 10);
41176         if(!zindex){
41177             zindex = this.getParentZIndex();
41178         }
41179         return (zindex || 12000) + 5;
41180     },
41181
41182     
41183     initList : function(){
41184         if(!this.list){
41185             var cls = 'x-combo-list',
41186                 listParent = Ext.getDom(this.getListParent() || Ext.getBody());
41187
41188             this.list = new Ext.Layer({
41189                 parentEl: listParent,
41190                 shadow: this.shadow,
41191                 cls: [cls, this.listClass].join(' '),
41192                 constrain:false,
41193                 zindex: this.getZIndex(listParent)
41194             });
41195
41196             var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
41197             this.list.setSize(lw, 0);
41198             this.list.swallowEvent('mousewheel');
41199             this.assetHeight = 0;
41200             if(this.syncFont !== false){
41201                 this.list.setStyle('font-size', this.el.getStyle('font-size'));
41202             }
41203             if(this.title){
41204                 this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
41205                 this.assetHeight += this.header.getHeight();
41206             }
41207
41208             this.innerList = this.list.createChild({cls:cls+'-inner'});
41209             this.mon(this.innerList, 'mouseover', this.onViewOver, this);
41210             this.mon(this.innerList, 'mousemove', this.onViewMove, this);
41211             this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
41212
41213             if(this.pageSize){
41214                 this.footer = this.list.createChild({cls:cls+'-ft'});
41215                 this.pageTb = new Ext.PagingToolbar({
41216                     store: this.store,
41217                     pageSize: this.pageSize,
41218                     renderTo:this.footer
41219                 });
41220                 this.assetHeight += this.footer.getHeight();
41221             }
41222
41223             if(!this.tpl){
41224                 
41225                 this.tpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>';
41226                 
41227             }
41228
41229             
41230             this.view = new Ext.DataView({
41231                 applyTo: this.innerList,
41232                 tpl: this.tpl,
41233                 singleSelect: true,
41234                 selectedClass: this.selectedClass,
41235                 itemSelector: this.itemSelector || '.' + cls + '-item',
41236                 emptyText: this.listEmptyText,
41237                 deferEmptyText: false
41238             });
41239
41240             this.mon(this.view, {
41241                 containerclick : this.onViewClick,
41242                 click : this.onViewClick,
41243                 scope :this
41244             });
41245
41246             this.bindStore(this.store, true);
41247
41248             if(this.resizable){
41249                 this.resizer = new Ext.Resizable(this.list,  {
41250                    pinned:true, handles:'se'
41251                 });
41252                 this.mon(this.resizer, 'resize', function(r, w, h){
41253                     this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
41254                     this.listWidth = w;
41255                     this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
41256                     this.restrictHeight();
41257                 }, this);
41258
41259                 this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
41260             }
41261         }
41262     },
41263
41264     
41265     getListParent : function() {
41266         return document.body;
41267     },
41268
41269     
41270     getStore : function(){
41271         return this.store;
41272     },
41273
41274     
41275     bindStore : function(store, initial){
41276         if(this.store && !initial){
41277             if(this.store !== store && this.store.autoDestroy){
41278                 this.store.destroy();
41279             }else{
41280                 this.store.un('beforeload', this.onBeforeLoad, this);
41281                 this.store.un('load', this.onLoad, this);
41282                 this.store.un('exception', this.collapse, this);
41283             }
41284             if(!store){
41285                 this.store = null;
41286                 if(this.view){
41287                     this.view.bindStore(null);
41288                 }
41289                 if(this.pageTb){
41290                     this.pageTb.bindStore(null);
41291                 }
41292             }
41293         }
41294         if(store){
41295             if(!initial) {
41296                 this.lastQuery = null;
41297                 if(this.pageTb) {
41298                     this.pageTb.bindStore(store);
41299                 }
41300             }
41301
41302             this.store = Ext.StoreMgr.lookup(store);
41303             this.store.on({
41304                 scope: this,
41305                 beforeload: this.onBeforeLoad,
41306                 load: this.onLoad,
41307                 exception: this.collapse
41308             });
41309
41310             if(this.view){
41311                 this.view.bindStore(store);
41312             }
41313         }
41314     },
41315
41316     reset : function(){
41317         if(this.clearFilterOnReset && this.mode == 'local'){
41318             this.store.clearFilter();
41319         }
41320         Ext.form.ComboBox.superclass.reset.call(this);
41321     },
41322
41323     
41324     initEvents : function(){
41325         Ext.form.ComboBox.superclass.initEvents.call(this);
41326
41327         
41328         this.keyNav = new Ext.KeyNav(this.el, {
41329             "up" : function(e){
41330                 this.inKeyMode = true;
41331                 this.selectPrev();
41332             },
41333
41334             "down" : function(e){
41335                 if(!this.isExpanded()){
41336                     this.onTriggerClick();
41337                 }else{
41338                     this.inKeyMode = true;
41339                     this.selectNext();
41340                 }
41341             },
41342
41343             "enter" : function(e){
41344                 this.onViewClick();
41345             },
41346
41347             "esc" : function(e){
41348                 this.collapse();
41349             },
41350
41351             "tab" : function(e){
41352                 if (this.forceSelection === true) {
41353                     this.collapse();
41354                 } else {
41355                     this.onViewClick(false);
41356                 }
41357                 return true;
41358             },
41359
41360             scope : this,
41361
41362             doRelay : function(e, h, hname){
41363                 if(hname == 'down' || this.scope.isExpanded()){
41364                     
41365                     var relay = Ext.KeyNav.prototype.doRelay.apply(this, arguments);
41366                     if(!Ext.isIE && Ext.EventManager.useKeydown){
41367                         
41368                         this.scope.fireKey(e);
41369                     }
41370                     return relay;
41371                 }
41372                 return true;
41373             },
41374
41375             forceKeyDown : true,
41376             defaultEventAction: 'stopEvent'
41377         });
41378         this.queryDelay = Math.max(this.queryDelay || 10,
41379                 this.mode == 'local' ? 10 : 250);
41380         this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);
41381         if(this.typeAhead){
41382             this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);
41383         }
41384         if(!this.enableKeyEvents){
41385             this.mon(this.el, 'keyup', this.onKeyUp, this);
41386         }
41387     },
41388
41389
41390     
41391     onDestroy : function(){
41392         if (this.dqTask){
41393             this.dqTask.cancel();
41394             this.dqTask = null;
41395         }
41396         this.bindStore(null);
41397         Ext.destroy(
41398             this.resizer,
41399             this.view,
41400             this.pageTb,
41401             this.list
41402         );
41403         Ext.destroyMembers(this, 'hiddenField');
41404         Ext.form.ComboBox.superclass.onDestroy.call(this);
41405     },
41406
41407     
41408     fireKey : function(e){
41409         if (!this.isExpanded()) {
41410             Ext.form.ComboBox.superclass.fireKey.call(this, e);
41411         }
41412     },
41413
41414     
41415     onResize : function(w, h){
41416         Ext.form.ComboBox.superclass.onResize.apply(this, arguments);
41417         if(!isNaN(w) && this.isVisible() && this.list){
41418             this.doResize(w);
41419         }else{
41420             this.bufferSize = w;
41421         }
41422     },
41423
41424     doResize: function(w){
41425         if(!Ext.isDefined(this.listWidth)){
41426             var lw = Math.max(w, this.minListWidth);
41427             this.list.setWidth(lw);
41428             this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
41429         }
41430     },
41431
41432     
41433     onEnable : function(){
41434         Ext.form.ComboBox.superclass.onEnable.apply(this, arguments);
41435         if(this.hiddenField){
41436             this.hiddenField.disabled = false;
41437         }
41438     },
41439
41440     
41441     onDisable : function(){
41442         Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);
41443         if(this.hiddenField){
41444             this.hiddenField.disabled = true;
41445         }
41446     },
41447
41448     
41449     onBeforeLoad : function(){
41450         if(!this.hasFocus){
41451             return;
41452         }
41453         this.innerList.update(this.loadingText ?
41454                '<div class="loading-indicator">'+this.loadingText+'</div>' : '');
41455         this.restrictHeight();
41456         this.selectedIndex = -1;
41457     },
41458
41459     
41460     onLoad : function(){
41461         if(!this.hasFocus){
41462             return;
41463         }
41464         if(this.store.getCount() > 0 || this.listEmptyText){
41465             this.expand();
41466             this.restrictHeight();
41467             if(this.lastQuery == this.allQuery){
41468                 if(this.editable){
41469                     this.el.dom.select();
41470                 }
41471
41472                 if(this.autoSelect !== false && !this.selectByValue(this.value, true)){
41473                     this.select(0, true);
41474                 }
41475             }else{
41476                 if(this.autoSelect !== false){
41477                     this.selectNext();
41478                 }
41479                 if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){
41480                     this.taTask.delay(this.typeAheadDelay);
41481                 }
41482             }
41483         }else{
41484             this.collapse();
41485         }
41486
41487     },
41488
41489     
41490     onTypeAhead : function(){
41491         if(this.store.getCount() > 0){
41492             var r = this.store.getAt(0);
41493             var newValue = r.data[this.displayField];
41494             var len = newValue.length;
41495             var selStart = this.getRawValue().length;
41496             if(selStart != len){
41497                 this.setRawValue(newValue);
41498                 this.selectText(selStart, newValue.length);
41499             }
41500         }
41501     },
41502
41503     
41504     assertValue : function(){
41505         var val = this.getRawValue(),
41506             rec;
41507
41508         if(this.valueField && Ext.isDefined(this.value)){
41509             rec = this.findRecord(this.valueField, this.value);
41510         }
41511         if(!rec || rec.get(this.displayField) != val){
41512             rec = this.findRecord(this.displayField, val);
41513         }
41514         if(!rec && this.forceSelection){
41515             if(val.length > 0 && val != this.emptyText){
41516                 this.el.dom.value = Ext.value(this.lastSelectionText, '');
41517                 this.applyEmptyText();
41518             }else{
41519                 this.clearValue();
41520             }
41521         }else{
41522             if(rec && this.valueField){
41523                 
41524                 
41525                 
41526                 if (this.value == val){
41527                     return;
41528                 }
41529                 val = rec.get(this.valueField || this.displayField);
41530             }
41531             this.setValue(val);
41532         }
41533     },
41534
41535     
41536     onSelect : function(record, index){
41537         if(this.fireEvent('beforeselect', this, record, index) !== false){
41538             this.setValue(record.data[this.valueField || this.displayField]);
41539             this.collapse();
41540             this.fireEvent('select', this, record, index);
41541         }
41542     },
41543
41544     
41545     getName: function(){
41546         var hf = this.hiddenField;
41547         return hf && hf.name ? hf.name : this.hiddenName || Ext.form.ComboBox.superclass.getName.call(this);
41548     },
41549
41550     
41551     getValue : function(){
41552         if(this.valueField){
41553             return Ext.isDefined(this.value) ? this.value : '';
41554         }else{
41555             return Ext.form.ComboBox.superclass.getValue.call(this);
41556         }
41557     },
41558
41559     
41560     clearValue : function(){
41561         if(this.hiddenField){
41562             this.hiddenField.value = '';
41563         }
41564         this.setRawValue('');
41565         this.lastSelectionText = '';
41566         this.applyEmptyText();
41567         this.value = '';
41568     },
41569
41570     
41571     setValue : function(v){
41572         var text = v;
41573         if(this.valueField){
41574             var r = this.findRecord(this.valueField, v);
41575             if(r){
41576                 text = r.data[this.displayField];
41577             }else if(Ext.isDefined(this.valueNotFoundText)){
41578                 text = this.valueNotFoundText;
41579             }
41580         }
41581         this.lastSelectionText = text;
41582         if(this.hiddenField){
41583             this.hiddenField.value = Ext.value(v, '');
41584         }
41585         Ext.form.ComboBox.superclass.setValue.call(this, text);
41586         this.value = v;
41587         return this;
41588     },
41589
41590     
41591     findRecord : function(prop, value){
41592         var record;
41593         if(this.store.getCount() > 0){
41594             this.store.each(function(r){
41595                 if(r.data[prop] == value){
41596                     record = r;
41597                     return false;
41598                 }
41599             });
41600         }
41601         return record;
41602     },
41603
41604     
41605     onViewMove : function(e, t){
41606         this.inKeyMode = false;
41607     },
41608
41609     
41610     onViewOver : function(e, t){
41611         if(this.inKeyMode){ 
41612             return;
41613         }
41614         var item = this.view.findItemFromChild(t);
41615         if(item){
41616             var index = this.view.indexOf(item);
41617             this.select(index, false);
41618         }
41619     },
41620
41621     
41622     onViewClick : function(doFocus){
41623         var index = this.view.getSelectedIndexes()[0],
41624             s = this.store,
41625             r = s.getAt(index);
41626         if(r){
41627             this.onSelect(r, index);
41628         }else {
41629             this.collapse();
41630         }
41631         if(doFocus !== false){
41632             this.el.focus();
41633         }
41634     },
41635
41636
41637     
41638     restrictHeight : function(){
41639         this.innerList.dom.style.height = '';
41640         var inner = this.innerList.dom,
41641             pad = this.list.getFrameWidth('tb') + (this.resizable ? this.handleHeight : 0) + this.assetHeight,
41642             h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight),
41643             ha = this.getPosition()[1]-Ext.getBody().getScroll().top,
41644             hb = Ext.lib.Dom.getViewHeight()-ha-this.getSize().height,
41645             space = Math.max(ha, hb, this.minHeight || 0)-this.list.shadowOffset-pad-5;
41646
41647         h = Math.min(h, space, this.maxHeight);
41648
41649         this.innerList.setHeight(h);
41650         this.list.beginUpdate();
41651         this.list.setHeight(h+pad);
41652         this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));
41653         this.list.endUpdate();
41654     },
41655
41656     
41657     isExpanded : function(){
41658         return this.list && this.list.isVisible();
41659     },
41660
41661     
41662     selectByValue : function(v, scrollIntoView){
41663         if(!Ext.isEmpty(v, true)){
41664             var r = this.findRecord(this.valueField || this.displayField, v);
41665             if(r){
41666                 this.select(this.store.indexOf(r), scrollIntoView);
41667                 return true;
41668             }
41669         }
41670         return false;
41671     },
41672
41673     
41674     select : function(index, scrollIntoView){
41675         this.selectedIndex = index;
41676         this.view.select(index);
41677         if(scrollIntoView !== false){
41678             var el = this.view.getNode(index);
41679             if(el){
41680                 this.innerList.scrollChildIntoView(el, false);
41681             }
41682         }
41683
41684     },
41685
41686     
41687     selectNext : function(){
41688         var ct = this.store.getCount();
41689         if(ct > 0){
41690             if(this.selectedIndex == -1){
41691                 this.select(0);
41692             }else if(this.selectedIndex < ct-1){
41693                 this.select(this.selectedIndex+1);
41694             }
41695         }
41696     },
41697
41698     
41699     selectPrev : function(){
41700         var ct = this.store.getCount();
41701         if(ct > 0){
41702             if(this.selectedIndex == -1){
41703                 this.select(0);
41704             }else if(this.selectedIndex !== 0){
41705                 this.select(this.selectedIndex-1);
41706             }
41707         }
41708     },
41709
41710     
41711     onKeyUp : function(e){
41712         var k = e.getKey();
41713         if(this.editable !== false && this.readOnly !== true && (k == e.BACKSPACE || !e.isSpecialKey())){
41714
41715             this.lastKey = k;
41716             this.dqTask.delay(this.queryDelay);
41717         }
41718         Ext.form.ComboBox.superclass.onKeyUp.call(this, e);
41719     },
41720
41721     
41722     validateBlur : function(){
41723         return !this.list || !this.list.isVisible();
41724     },
41725
41726     
41727     initQuery : function(){
41728         this.doQuery(this.getRawValue());
41729     },
41730
41731     
41732     beforeBlur : function(){
41733         this.assertValue();
41734     },
41735
41736     
41737     postBlur  : function(){
41738         Ext.form.ComboBox.superclass.postBlur.call(this);
41739         this.collapse();
41740         this.inKeyMode = false;
41741     },
41742
41743     
41744     doQuery : function(q, forceAll){
41745         q = Ext.isEmpty(q) ? '' : q;
41746         var qe = {
41747             query: q,
41748             forceAll: forceAll,
41749             combo: this,
41750             cancel:false
41751         };
41752         if(this.fireEvent('beforequery', qe)===false || qe.cancel){
41753             return false;
41754         }
41755         q = qe.query;
41756         forceAll = qe.forceAll;
41757         if(forceAll === true || (q.length >= this.minChars)){
41758             if(this.lastQuery !== q){
41759                 this.lastQuery = q;
41760                 if(this.mode == 'local'){
41761                     this.selectedIndex = -1;
41762                     if(forceAll){
41763                         this.store.clearFilter();
41764                     }else{
41765                         this.store.filter(this.displayField, q);
41766                     }
41767                     this.onLoad();
41768                 }else{
41769                     this.store.baseParams[this.queryParam] = q;
41770                     this.store.load({
41771                         params: this.getParams(q)
41772                     });
41773                     this.expand();
41774                 }
41775             }else{
41776                 this.selectedIndex = -1;
41777                 this.onLoad();
41778             }
41779         }
41780     },
41781
41782     
41783     getParams : function(q){
41784         var params = {},
41785             paramNames = this.store.paramNames;
41786         if(this.pageSize){
41787             params[paramNames.start] = 0;
41788             params[paramNames.limit] = this.pageSize;
41789         }
41790         return params;
41791     },
41792
41793     
41794     collapse : function(){
41795         if(!this.isExpanded()){
41796             return;
41797         }
41798         this.list.hide();
41799         Ext.getDoc().un('mousewheel', this.collapseIf, this);
41800         Ext.getDoc().un('mousedown', this.collapseIf, this);
41801         this.fireEvent('collapse', this);
41802     },
41803
41804     
41805     collapseIf : function(e){
41806         if(!this.isDestroyed && !e.within(this.wrap) && !e.within(this.list)){
41807             this.collapse();
41808         }
41809     },
41810
41811     
41812     expand : function(){
41813         if(this.isExpanded() || !this.hasFocus){
41814             return;
41815         }
41816
41817         if(this.title || this.pageSize){
41818             this.assetHeight = 0;
41819             if(this.title){
41820                 this.assetHeight += this.header.getHeight();
41821             }
41822             if(this.pageSize){
41823                 this.assetHeight += this.footer.getHeight();
41824             }
41825         }
41826
41827         if(this.bufferSize){
41828             this.doResize(this.bufferSize);
41829             delete this.bufferSize;
41830         }
41831         this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));
41832
41833         
41834         this.list.setZIndex(this.getZIndex());
41835         this.list.show();
41836         if(Ext.isGecko2){
41837             this.innerList.setOverflow('auto'); 
41838         }
41839         this.mon(Ext.getDoc(), {
41840             scope: this,
41841             mousewheel: this.collapseIf,
41842             mousedown: this.collapseIf
41843         });
41844         this.fireEvent('expand', this);
41845     },
41846
41847     
41848     
41849     
41850     onTriggerClick : function(){
41851         if(this.readOnly || this.disabled){
41852             return;
41853         }
41854         if(this.isExpanded()){
41855             this.collapse();
41856             this.el.focus();
41857         }else {
41858             this.onFocus({});
41859             if(this.triggerAction == 'all') {
41860                 this.doQuery(this.allQuery, true);
41861             } else {
41862                 this.doQuery(this.getRawValue());
41863             }
41864             this.el.focus();
41865         }
41866     }
41867
41868     
41869     
41870     
41871     
41872
41873 });
41874 Ext.reg('combo', Ext.form.ComboBox);
41875
41876 Ext.form.Checkbox = Ext.extend(Ext.form.Field,  {
41877     
41878     focusClass : undefined,
41879     
41880     fieldClass : 'x-form-field',
41881     
41882     checked : false,
41883     
41884     boxLabel: '&#160;',
41885     
41886     defaultAutoCreate : { tag: 'input', type: 'checkbox', autocomplete: 'off'},
41887     
41888     
41889     
41890
41891     
41892     actionMode : 'wrap',
41893
41894         
41895     initComponent : function(){
41896         Ext.form.Checkbox.superclass.initComponent.call(this);
41897         this.addEvents(
41898             
41899             'check'
41900         );
41901     },
41902
41903     
41904     onResize : function(){
41905         Ext.form.Checkbox.superclass.onResize.apply(this, arguments);
41906         if(!this.boxLabel && !this.fieldLabel){
41907             this.el.alignTo(this.wrap, 'c-c');
41908         }
41909     },
41910
41911     
41912     initEvents : function(){
41913         Ext.form.Checkbox.superclass.initEvents.call(this);
41914         this.mon(this.el, {
41915             scope: this,
41916             click: this.onClick,
41917             change: this.onClick
41918         });
41919     },
41920
41921     
41922     markInvalid : Ext.emptyFn,
41923     
41924     clearInvalid : Ext.emptyFn,
41925
41926     
41927     onRender : function(ct, position){
41928         Ext.form.Checkbox.superclass.onRender.call(this, ct, position);
41929         if(this.inputValue !== undefined){
41930             this.el.dom.value = this.inputValue;
41931         }
41932         this.wrap = this.el.wrap({cls: 'x-form-check-wrap'});
41933         if(this.boxLabel){
41934             this.wrap.createChild({tag: 'label', htmlFor: this.el.id, cls: 'x-form-cb-label', html: this.boxLabel});
41935         }
41936         if(this.checked){
41937             this.setValue(true);
41938         }else{
41939             this.checked = this.el.dom.checked;
41940         }
41941         
41942         if (Ext.isIE && !Ext.isStrict) {
41943             this.wrap.repaint();
41944         }
41945         this.resizeEl = this.positionEl = this.wrap;
41946     },
41947
41948     
41949     onDestroy : function(){
41950         Ext.destroy(this.wrap);
41951         Ext.form.Checkbox.superclass.onDestroy.call(this);
41952     },
41953
41954     
41955     initValue : function() {
41956         this.originalValue = this.getValue();
41957     },
41958
41959     
41960     getValue : function(){
41961         if(this.rendered){
41962             return this.el.dom.checked;
41963         }
41964         return this.checked;
41965     },
41966
41967         
41968     onClick : function(){
41969         if(this.el.dom.checked != this.checked){
41970             this.setValue(this.el.dom.checked);
41971         }
41972     },
41973
41974     
41975     setValue : function(v){
41976         var checked = this.checked,
41977             inputVal = this.inputValue;
41978             
41979         this.checked = (v === true || v === 'true' || v == '1' || (inputVal ? v == inputVal : String(v).toLowerCase() == 'on'));
41980         if(this.rendered){
41981             this.el.dom.checked = this.checked;
41982             this.el.dom.defaultChecked = this.checked;
41983         }
41984         if(checked != this.checked){
41985             this.fireEvent('check', this, this.checked);
41986             if(this.handler){
41987                 this.handler.call(this.scope || this, this, this.checked);
41988             }
41989         }
41990         return this;
41991     }
41992 });
41993 Ext.reg('checkbox', Ext.form.Checkbox);
41994
41995 Ext.form.CheckboxGroup = Ext.extend(Ext.form.Field, {
41996     
41997     
41998     columns : 'auto',
41999     
42000     vertical : false,
42001     
42002     allowBlank : true,
42003     
42004     blankText : "You must select at least one item in this group",
42005
42006     
42007     defaultType : 'checkbox',
42008
42009     
42010     groupCls : 'x-form-check-group',
42011
42012     
42013     initComponent: function(){
42014         this.addEvents(
42015             
42016             'change'
42017         );
42018         this.on('change', this.validate, this);
42019         Ext.form.CheckboxGroup.superclass.initComponent.call(this);
42020     },
42021
42022     
42023     onRender : function(ct, position){
42024         if(!this.el){
42025             var panelCfg = {
42026                 autoEl: {
42027                     id: this.id
42028                 },
42029                 cls: this.groupCls,
42030                 layout: 'column',
42031                 renderTo: ct,
42032                 bufferResize: false 
42033             };
42034             var colCfg = {
42035                 xtype: 'container',
42036                 defaultType: this.defaultType,
42037                 layout: 'form',
42038                 defaults: {
42039                     hideLabel: true,
42040                     anchor: '100%'
42041                 }
42042             };
42043
42044             if(this.items[0].items){
42045
42046                 
42047
42048                 Ext.apply(panelCfg, {
42049                     layoutConfig: {columns: this.items.length},
42050                     defaults: this.defaults,
42051                     items: this.items
42052                 });
42053                 for(var i=0, len=this.items.length; i<len; i++){
42054                     Ext.applyIf(this.items[i], colCfg);
42055                 }
42056
42057             }else{
42058
42059                 
42060                 
42061
42062                 var numCols, cols = [];
42063
42064                 if(typeof this.columns == 'string'){ 
42065                     this.columns = this.items.length;
42066                 }
42067                 if(!Ext.isArray(this.columns)){
42068                     var cs = [];
42069                     for(var i=0; i<this.columns; i++){
42070                         cs.push((100/this.columns)*.01); 
42071                     }
42072                     this.columns = cs;
42073                 }
42074
42075                 numCols = this.columns.length;
42076
42077                 
42078                 for(var i=0; i<numCols; i++){
42079                     var cc = Ext.apply({items:[]}, colCfg);
42080                     cc[this.columns[i] <= 1 ? 'columnWidth' : 'width'] = this.columns[i];
42081                     if(this.defaults){
42082                         cc.defaults = Ext.apply(cc.defaults || {}, this.defaults);
42083                     }
42084                     cols.push(cc);
42085                 };
42086
42087                 
42088                 if(this.vertical){
42089                     var rows = Math.ceil(this.items.length / numCols), ri = 0;
42090                     for(var i=0, len=this.items.length; i<len; i++){
42091                         if(i>0 && i%rows==0){
42092                             ri++;
42093                         }
42094                         if(this.items[i].fieldLabel){
42095                             this.items[i].hideLabel = false;
42096                         }
42097                         cols[ri].items.push(this.items[i]);
42098                     };
42099                 }else{
42100                     for(var i=0, len=this.items.length; i<len; i++){
42101                         var ci = i % numCols;
42102                         if(this.items[i].fieldLabel){
42103                             this.items[i].hideLabel = false;
42104                         }
42105                         cols[ci].items.push(this.items[i]);
42106                     };
42107                 }
42108
42109                 Ext.apply(panelCfg, {
42110                     layoutConfig: {columns: numCols},
42111                     items: cols
42112                 });
42113             }
42114
42115             this.panel = new Ext.Container(panelCfg);
42116             this.panel.ownerCt = this;
42117             this.el = this.panel.getEl();
42118
42119             if(this.forId && this.itemCls){
42120                 var l = this.el.up(this.itemCls).child('label', true);
42121                 if(l){
42122                     l.setAttribute('htmlFor', this.forId);
42123                 }
42124             }
42125
42126             var fields = this.panel.findBy(function(c){
42127                 return c.isFormField;
42128             }, this);
42129
42130             this.items = new Ext.util.MixedCollection();
42131             this.items.addAll(fields);
42132         }
42133         Ext.form.CheckboxGroup.superclass.onRender.call(this, ct, position);
42134     },
42135
42136     initValue : function(){
42137         if(this.value){
42138             this.setValue.apply(this, this.buffered ? this.value : [this.value]);
42139             delete this.buffered;
42140             delete this.value;
42141         }
42142     },
42143
42144     afterRender : function(){
42145         Ext.form.CheckboxGroup.superclass.afterRender.call(this);
42146         this.eachItem(function(item){
42147             item.on('check', this.fireChecked, this);
42148             item.inGroup = true;
42149         });
42150     },
42151
42152     
42153     doLayout: function(){
42154         
42155         if(this.rendered){
42156             this.panel.forceLayout = this.ownerCt.forceLayout;
42157             this.panel.doLayout();
42158         }
42159     },
42160
42161     
42162     fireChecked: function(){
42163         var arr = [];
42164         this.eachItem(function(item){
42165             if(item.checked){
42166                 arr.push(item);
42167             }
42168         });
42169         this.fireEvent('change', this, arr);
42170     },
42171     
42172     
42173     getErrors: function() {
42174         var errors = Ext.form.CheckboxGroup.superclass.getErrors.apply(this, arguments);
42175         
42176         if (!this.allowBlank) {
42177             var blank = true;
42178             
42179             this.eachItem(function(f){
42180                 if (f.checked) {
42181                     return (blank = false);
42182                 }
42183             });
42184             
42185             if (blank) errors.push(this.blankText);
42186         }
42187         
42188         return errors;
42189     },
42190
42191     
42192     isDirty: function(){
42193         
42194         if (this.disabled || !this.rendered) {
42195             return false;
42196         }
42197
42198         var dirty = false;
42199         
42200         this.eachItem(function(item){
42201             if(item.isDirty()){
42202                 dirty = true;
42203                 return false;
42204             }
42205         });
42206         
42207         return dirty;
42208     },
42209
42210     
42211     setReadOnly : function(readOnly){
42212         if(this.rendered){
42213             this.eachItem(function(item){
42214                 item.setReadOnly(readOnly);
42215             });
42216         }
42217         this.readOnly = readOnly;
42218     },
42219
42220     
42221     onDisable : function(){
42222         this.eachItem(function(item){
42223             item.disable();
42224         });
42225     },
42226
42227     
42228     onEnable : function(){
42229         this.eachItem(function(item){
42230             item.enable();
42231         });
42232     },
42233
42234     
42235     onResize : function(w, h){
42236         this.panel.setSize(w, h);
42237         this.panel.doLayout();
42238     },
42239
42240     
42241     reset : function(){
42242         if (this.originalValue) {
42243             
42244             this.eachItem(function(c){
42245                 if(c.setValue){
42246                     c.setValue(false);
42247                     c.originalValue = c.getValue();
42248                 }
42249             });
42250             
42251             
42252             this.resetOriginal = true;
42253             this.setValue(this.originalValue);
42254             delete this.resetOriginal;
42255         } else {
42256             this.eachItem(function(c){
42257                 if(c.reset){
42258                     c.reset();
42259                 }
42260             });
42261         }
42262         
42263         
42264         (function() {
42265             this.clearInvalid();
42266         }).defer(50, this);
42267     },
42268
42269     
42270     setValue: function(){
42271         if(this.rendered){
42272             this.onSetValue.apply(this, arguments);
42273         }else{
42274             this.buffered = true;
42275             this.value = arguments;
42276         }
42277         return this;
42278     },
42279
42280     
42281     onSetValue: function(id, value){
42282         if(arguments.length == 1){
42283             if(Ext.isArray(id)){
42284                 Ext.each(id, function(val, idx){
42285                     if (Ext.isObject(val) && val.setValue){ 
42286                         val.setValue(true);
42287                         if (this.resetOriginal === true) {
42288                             val.originalValue = val.getValue();
42289                         }
42290                     } else { 
42291                         var item = this.items.itemAt(idx);
42292                         if(item){
42293                             item.setValue(val);
42294                         }
42295                     }
42296                 }, this);
42297             }else if(Ext.isObject(id)){
42298                 
42299                 for(var i in id){
42300                     var f = this.getBox(i);
42301                     if(f){
42302                         f.setValue(id[i]);
42303                     }
42304                 }
42305             }else{
42306                 this.setValueForItem(id);
42307             }
42308         }else{
42309             var f = this.getBox(id);
42310             if(f){
42311                 f.setValue(value);
42312             }
42313         }
42314     },
42315
42316     
42317     beforeDestroy: function(){
42318         Ext.destroy(this.panel);
42319         if (!this.rendered) {
42320             Ext.destroy(this.items);
42321         }
42322         Ext.form.CheckboxGroup.superclass.beforeDestroy.call(this);
42323
42324     },
42325
42326     setValueForItem : function(val){
42327         val = String(val).split(',');
42328         this.eachItem(function(item){
42329             if(val.indexOf(item.inputValue)> -1){
42330                 item.setValue(true);
42331             }
42332         });
42333     },
42334
42335     
42336     getBox : function(id){
42337         var box = null;
42338         this.eachItem(function(f){
42339             if(id == f || f.dataIndex == id || f.id == id || f.getName() == id){
42340                 box = f;
42341                 return false;
42342             }
42343         });
42344         return box;
42345     },
42346
42347     
42348     getValue : function(){
42349         var out = [];
42350         this.eachItem(function(item){
42351             if(item.checked){
42352                 out.push(item);
42353             }
42354         });
42355         return out;
42356     },
42357
42358     
42359     eachItem: function(fn, scope) {
42360         if(this.items && this.items.each){
42361             this.items.each(fn, scope || this);
42362         }
42363     },
42364
42365     
42366
42367     
42368     getRawValue : Ext.emptyFn,
42369
42370     
42371     setRawValue : Ext.emptyFn
42372
42373 });
42374
42375 Ext.reg('checkboxgroup', Ext.form.CheckboxGroup);
42376
42377 Ext.form.CompositeField = Ext.extend(Ext.form.Field, {
42378
42379     
42380     defaultMargins: '0 5 0 0',
42381
42382     
42383     skipLastItemMargin: true,
42384
42385     
42386     isComposite: true,
42387
42388     
42389     combineErrors: true,
42390     
42391     
42392     labelConnector: ', ',
42393     
42394     
42395
42396     
42397     
42398     initComponent: function() {
42399         var labels = [],
42400             items  = this.items,
42401             item;
42402
42403         for (var i=0, j = items.length; i < j; i++) {
42404             item = items[i];
42405             
42406             if (!Ext.isEmpty(item.ref)){
42407                 item.ref = '../' + item.ref;
42408             }
42409
42410             labels.push(item.fieldLabel);
42411
42412             
42413             Ext.applyIf(item, this.defaults);
42414
42415             
42416             if (!(i == j - 1 && this.skipLastItemMargin)) {
42417                 Ext.applyIf(item, {margins: this.defaultMargins});
42418             }
42419         }
42420
42421         this.fieldLabel = this.fieldLabel || this.buildLabel(labels);
42422
42423         
42424         this.fieldErrors = new Ext.util.MixedCollection(true, function(item) {
42425             return item.field;
42426         });
42427
42428         this.fieldErrors.on({
42429             scope  : this,
42430             add    : this.updateInvalidMark,
42431             remove : this.updateInvalidMark,
42432             replace: this.updateInvalidMark
42433         });
42434
42435         Ext.form.CompositeField.superclass.initComponent.apply(this, arguments);
42436         
42437         this.innerCt = new Ext.Container({
42438             layout  : 'hbox',
42439             items   : this.items,
42440             cls     : 'x-form-composite',
42441             defaultMargins: '0 3 0 0',
42442             ownerCt: this
42443         });
42444         this.innerCt.ownerCt = undefined;
42445         
42446         var fields = this.innerCt.findBy(function(c) {
42447             return c.isFormField;
42448         }, this);
42449
42450         
42451         this.items = new Ext.util.MixedCollection();
42452         this.items.addAll(fields);
42453         
42454     },
42455
42456     
42457     onRender: function(ct, position) {
42458         if (!this.el) {
42459             
42460             var innerCt = this.innerCt;
42461             innerCt.render(ct);
42462
42463             this.el = innerCt.getEl();
42464
42465             
42466             
42467             if (this.combineErrors) {
42468                 this.eachItem(function(field) {
42469                     Ext.apply(field, {
42470                         markInvalid : this.onFieldMarkInvalid.createDelegate(this, [field], 0),
42471                         clearInvalid: this.onFieldClearInvalid.createDelegate(this, [field], 0)
42472                     });
42473                 });
42474             }
42475
42476             
42477             var l = this.el.parent().parent().child('label', true);
42478             if (l) {
42479                 l.setAttribute('for', this.items.items[0].id);
42480             }
42481         }
42482
42483         Ext.form.CompositeField.superclass.onRender.apply(this, arguments);
42484     },
42485
42486     
42487     onFieldMarkInvalid: function(field, message) {
42488         var name  = field.getName(),
42489             error = {
42490                 field: name, 
42491                 errorName: field.fieldLabel || name,
42492                 error: message
42493             };
42494
42495         this.fieldErrors.replace(name, error);
42496
42497         field.el.addClass(field.invalidClass);
42498     },
42499
42500     
42501     onFieldClearInvalid: function(field) {
42502         this.fieldErrors.removeKey(field.getName());
42503
42504         field.el.removeClass(field.invalidClass);
42505     },
42506
42507     
42508     updateInvalidMark: function() {
42509         var ieStrict = Ext.isIE6 && Ext.isStrict;
42510
42511         if (this.fieldErrors.length == 0) {
42512             this.clearInvalid();
42513
42514             
42515             if (ieStrict) {
42516                 this.clearInvalid.defer(50, this);
42517             }
42518         } else {
42519             var message = this.buildCombinedErrorMessage(this.fieldErrors.items);
42520
42521             this.sortErrors();
42522             this.markInvalid(message);
42523
42524             
42525             if (ieStrict) {
42526                 this.markInvalid(message);
42527             }
42528         }
42529     },
42530
42531     
42532     validateValue: function() {
42533         var valid = true;
42534
42535         this.eachItem(function(field) {
42536             if (!field.isValid()) valid = false;
42537         });
42538
42539         return valid;
42540     },
42541
42542     
42543     buildCombinedErrorMessage: function(errors) {
42544         var combined = [],
42545             error;
42546
42547         for (var i = 0, j = errors.length; i < j; i++) {
42548             error = errors[i];
42549
42550             combined.push(String.format("{0}: {1}", error.errorName, error.error));
42551         }
42552
42553         return combined.join("<br />");
42554     },
42555
42556     
42557     sortErrors: function() {
42558         var fields = this.items;
42559
42560         this.fieldErrors.sort("ASC", function(a, b) {
42561             var findByName = function(key) {
42562                 return function(field) {
42563                     return field.getName() == key;
42564                 };
42565             };
42566
42567             var aIndex = fields.findIndexBy(findByName(a.field)),
42568                 bIndex = fields.findIndexBy(findByName(b.field));
42569
42570             return aIndex < bIndex ? -1 : 1;
42571         });
42572     },
42573
42574     
42575     reset: function() {
42576         this.eachItem(function(item) {
42577             item.reset();
42578         });
42579
42580         
42581         
42582         (function() {
42583             this.clearInvalid();
42584         }).defer(50, this);
42585     },
42586     
42587     
42588     clearInvalidChildren: function() {
42589         this.eachItem(function(item) {
42590             item.clearInvalid();
42591         });
42592     },
42593
42594     
42595     buildLabel: function(segments) {
42596         return Ext.clean(segments).join(this.labelConnector);
42597     },
42598
42599     
42600     isDirty: function(){
42601         
42602         if (this.disabled || !this.rendered) {
42603             return false;
42604         }
42605
42606         var dirty = false;
42607         this.eachItem(function(item){
42608             if(item.isDirty()){
42609                 dirty = true;
42610                 return false;
42611             }
42612         });
42613         return dirty;
42614     },
42615
42616     
42617     eachItem: function(fn, scope) {
42618         if(this.items && this.items.each){
42619             this.items.each(fn, scope || this);
42620         }
42621     },
42622
42623     
42624     onResize: function(adjWidth, adjHeight, rawWidth, rawHeight) {
42625         var innerCt = this.innerCt;
42626
42627         if (this.rendered && innerCt.rendered) {
42628             innerCt.setSize(adjWidth, adjHeight);
42629         }
42630
42631         Ext.form.CompositeField.superclass.onResize.apply(this, arguments);
42632     },
42633
42634     
42635     doLayout: function(shallow, force) {
42636         if (this.rendered) {
42637             var innerCt = this.innerCt;
42638
42639             innerCt.forceLayout = this.ownerCt.forceLayout;
42640             innerCt.doLayout(shallow, force);
42641         }
42642     },
42643
42644     
42645     beforeDestroy: function(){
42646         Ext.destroy(this.innerCt);
42647
42648         Ext.form.CompositeField.superclass.beforeDestroy.call(this);
42649     },
42650
42651     
42652     setReadOnly : function(readOnly) {
42653         if (readOnly == undefined) {
42654             readOnly = true;
42655         }
42656         readOnly = !!readOnly;
42657
42658         if(this.rendered){
42659             this.eachItem(function(item){
42660                 item.setReadOnly(readOnly);
42661             });
42662         }
42663         this.readOnly = readOnly;
42664     },
42665
42666     onShow : function() {
42667         Ext.form.CompositeField.superclass.onShow.call(this);
42668         this.doLayout();
42669     },
42670
42671     
42672     onDisable : function(){
42673         this.eachItem(function(item){
42674             item.disable();
42675         });
42676     },
42677
42678     
42679     onEnable : function(){
42680         this.eachItem(function(item){
42681             item.enable();
42682         });
42683     }
42684 });
42685
42686 Ext.reg('compositefield', Ext.form.CompositeField);
42687 Ext.form.Radio = Ext.extend(Ext.form.Checkbox, {
42688     inputType: 'radio',
42689
42690     
42691     markInvalid : Ext.emptyFn,
42692     
42693     clearInvalid : Ext.emptyFn,
42694
42695     
42696     getGroupValue : function(){
42697         var p = this.el.up('form') || Ext.getBody();
42698         var c = p.child('input[name='+this.el.dom.name+']:checked', true);
42699         return c ? c.value : null;
42700     },
42701
42702     
42703     setValue : function(v){
42704         var checkEl,
42705             els,
42706             radio;
42707         if (typeof v == 'boolean') {
42708             Ext.form.Radio.superclass.setValue.call(this, v);
42709         } else if (this.rendered) {
42710             checkEl = this.getCheckEl();
42711             radio = checkEl.child('input[name=' + this.el.dom.name + '][value=' + v + ']', true);
42712             if(radio){
42713                 Ext.getCmp(radio.id).setValue(true);
42714             }
42715         }
42716         if(this.rendered && this.checked){
42717             checkEl = checkEl || this.getCheckEl();
42718             els = this.getCheckEl().select('input[name=' + this.el.dom.name + ']');
42719                         els.each(function(el){
42720                                 if(el.dom.id != this.id){
42721                                         Ext.getCmp(el.dom.id).setValue(false);
42722                                 }
42723                         }, this);
42724         }
42725         return this;
42726     },
42727
42728     
42729     getCheckEl: function(){
42730         if(this.inGroup){
42731             return this.el.up('.x-form-radio-group');
42732         }
42733         return this.el.up('form') || Ext.getBody();
42734     }
42735 });
42736 Ext.reg('radio', Ext.form.Radio);
42737
42738 Ext.form.RadioGroup = Ext.extend(Ext.form.CheckboxGroup, {
42739     
42740     
42741     allowBlank : true,
42742     
42743     blankText : 'You must select one item in this group',
42744     
42745     
42746     defaultType : 'radio',
42747     
42748     
42749     groupCls : 'x-form-radio-group',
42750     
42751     
42752     
42753     
42754     getValue : function(){
42755         var out = null;
42756         this.eachItem(function(item){
42757             if(item.checked){
42758                 out = item;
42759                 return false;
42760             }
42761         });
42762         return out;
42763     },
42764     
42765     
42766     onSetValue : function(id, value){
42767         if(arguments.length > 1){
42768             var f = this.getBox(id);
42769             if(f){
42770                 f.setValue(value);
42771                 if(f.checked){
42772                     this.eachItem(function(item){
42773                         if (item !== f){
42774                             item.setValue(false);
42775                         }
42776                     });
42777                 }
42778             }
42779         }else{
42780             this.setValueForItem(id);
42781         }
42782     },
42783     
42784     setValueForItem : function(val){
42785         val = String(val).split(',')[0];
42786         this.eachItem(function(item){
42787             item.setValue(val == item.inputValue);
42788         });
42789     },
42790     
42791     
42792     fireChecked : function(){
42793         if(!this.checkTask){
42794             this.checkTask = new Ext.util.DelayedTask(this.bufferChecked, this);
42795         }
42796         this.checkTask.delay(10);
42797     },
42798     
42799     
42800     bufferChecked : function(){
42801         var out = null;
42802         this.eachItem(function(item){
42803             if(item.checked){
42804                 out = item;
42805                 return false;
42806             }
42807         });
42808         this.fireEvent('change', this, out);
42809     },
42810     
42811     onDestroy : function(){
42812         if(this.checkTask){
42813             this.checkTask.cancel();
42814             this.checkTask = null;
42815         }
42816         Ext.form.RadioGroup.superclass.onDestroy.call(this);
42817     }
42818
42819 });
42820
42821 Ext.reg('radiogroup', Ext.form.RadioGroup);
42822
42823 Ext.form.Hidden = Ext.extend(Ext.form.Field, {
42824     
42825     inputType : 'hidden',
42826     
42827     shouldLayout: false,
42828
42829     
42830     onRender : function(){
42831         Ext.form.Hidden.superclass.onRender.apply(this, arguments);
42832     },
42833
42834     
42835     initEvents : function(){
42836         this.originalValue = this.getValue();
42837     },
42838
42839     
42840     setSize : Ext.emptyFn,
42841     setWidth : Ext.emptyFn,
42842     setHeight : Ext.emptyFn,
42843     setPosition : Ext.emptyFn,
42844     setPagePosition : Ext.emptyFn,
42845     markInvalid : Ext.emptyFn,
42846     clearInvalid : Ext.emptyFn
42847 });
42848 Ext.reg('hidden', Ext.form.Hidden);
42849 Ext.form.BasicForm = Ext.extend(Ext.util.Observable, {
42850
42851     constructor: function(el, config){
42852         Ext.apply(this, config);
42853         if(Ext.isString(this.paramOrder)){
42854             this.paramOrder = this.paramOrder.split(/[\s,|]/);
42855         }
42856         
42857         this.items = new Ext.util.MixedCollection(false, function(o){
42858             return o.getItemId();
42859         });
42860         this.addEvents(
42861             
42862             'beforeaction',
42863             
42864             'actionfailed',
42865             
42866             'actioncomplete'
42867         );
42868
42869         if(el){
42870             this.initEl(el);
42871         }
42872         Ext.form.BasicForm.superclass.constructor.call(this);
42873     },
42874
42875     
42876     
42877     
42878     
42879     
42880     
42881     
42882     timeout: 30,
42883
42884     
42885
42886     
42887     paramOrder: undefined,
42888
42889     
42890     paramsAsHash: false,
42891
42892     
42893     waitTitle: 'Please Wait...',
42894
42895     
42896     activeAction : null,
42897
42898     
42899     trackResetOnLoad : false,
42900
42901     
42902     
42903
42904     
42905     initEl : function(el){
42906         this.el = Ext.get(el);
42907         this.id = this.el.id || Ext.id();
42908         if(!this.standardSubmit){
42909             this.el.on('submit', this.onSubmit, this);
42910         }
42911         this.el.addClass('x-form');
42912     },
42913
42914     
42915     getEl: function(){
42916         return this.el;
42917     },
42918
42919     
42920     onSubmit : function(e){
42921         e.stopEvent();
42922     },
42923
42924     
42925     destroy: function(bound){
42926         if(bound !== true){
42927             this.items.each(function(f){
42928                 Ext.destroy(f);
42929             });
42930             Ext.destroy(this.el);
42931         }
42932         this.items.clear();
42933         this.purgeListeners();
42934     },
42935
42936     
42937     isValid : function(){
42938         var valid = true;
42939         this.items.each(function(f){
42940            if(!f.validate()){
42941                valid = false;
42942            }
42943         });
42944         return valid;
42945     },
42946
42947     
42948     isDirty : function(){
42949         var dirty = false;
42950         this.items.each(function(f){
42951            if(f.isDirty()){
42952                dirty = true;
42953                return false;
42954            }
42955         });
42956         return dirty;
42957     },
42958
42959     
42960     doAction : function(action, options){
42961         if(Ext.isString(action)){
42962             action = new Ext.form.Action.ACTION_TYPES[action](this, options);
42963         }
42964         if(this.fireEvent('beforeaction', this, action) !== false){
42965             this.beforeAction(action);
42966             action.run.defer(100, action);
42967         }
42968         return this;
42969     },
42970
42971     
42972     submit : function(options){
42973         options = options || {};
42974         if(this.standardSubmit){
42975             var v = options.clientValidation === false || this.isValid();
42976             if(v){
42977                 var el = this.el.dom;
42978                 if(this.url && Ext.isEmpty(el.action)){
42979                     el.action = this.url;
42980                 }
42981                 el.submit();
42982             }
42983             return v;
42984         }
42985         var submitAction = String.format('{0}submit', this.api ? 'direct' : '');
42986         this.doAction(submitAction, options);
42987         return this;
42988     },
42989
42990     
42991     load : function(options){
42992         var loadAction = String.format('{0}load', this.api ? 'direct' : '');
42993         this.doAction(loadAction, options);
42994         return this;
42995     },
42996
42997     
42998     updateRecord : function(record){
42999         record.beginEdit();
43000         var fs = record.fields,
43001             field,
43002             value;
43003         fs.each(function(f){
43004             field = this.findField(f.name);
43005             if(field){
43006                 value = field.getValue();
43007                 if (typeof value != undefined && value.getGroupValue) {
43008                     value = value.getGroupValue();
43009                 } else if ( field.eachItem ) {
43010                     value = [];
43011                     field.eachItem(function(item){
43012                         value.push(item.getValue());
43013                     });
43014                 }
43015                 record.set(f.name, value);
43016             }
43017         }, this);
43018         record.endEdit();
43019         return this;
43020     },
43021
43022     
43023     loadRecord : function(record){
43024         this.setValues(record.data);
43025         return this;
43026     },
43027
43028     
43029     beforeAction : function(action){
43030         
43031         this.items.each(function(f){
43032             if(f.isFormField && f.syncValue){
43033                 f.syncValue();
43034             }
43035         });
43036         var o = action.options;
43037         if(o.waitMsg){
43038             if(this.waitMsgTarget === true){
43039                 this.el.mask(o.waitMsg, 'x-mask-loading');
43040             }else if(this.waitMsgTarget){
43041                 this.waitMsgTarget = Ext.get(this.waitMsgTarget);
43042                 this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');
43043             }else{
43044                 Ext.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle);
43045             }
43046         }
43047     },
43048
43049     
43050     afterAction : function(action, success){
43051         this.activeAction = null;
43052         var o = action.options;
43053         if(o.waitMsg){
43054             if(this.waitMsgTarget === true){
43055                 this.el.unmask();
43056             }else if(this.waitMsgTarget){
43057                 this.waitMsgTarget.unmask();
43058             }else{
43059                 Ext.MessageBox.updateProgress(1);
43060                 Ext.MessageBox.hide();
43061             }
43062         }
43063         if(success){
43064             if(o.reset){
43065                 this.reset();
43066             }
43067             Ext.callback(o.success, o.scope, [this, action]);
43068             this.fireEvent('actioncomplete', this, action);
43069         }else{
43070             Ext.callback(o.failure, o.scope, [this, action]);
43071             this.fireEvent('actionfailed', this, action);
43072         }
43073     },
43074
43075     
43076     findField : function(id) {
43077         var field = this.items.get(id);
43078
43079         if (!Ext.isObject(field)) {
43080             
43081             var findMatchingField = function(f) {
43082                 if (f.isFormField) {
43083                     if (f.dataIndex == id || f.id == id || f.getName() == id) {
43084                         field = f;
43085                         return false;
43086                     } else if (f.isComposite) {
43087                         return f.items.each(findMatchingField);
43088                     } else if (f instanceof Ext.form.CheckboxGroup && f.rendered) {
43089                         return f.eachItem(findMatchingField);
43090                     }
43091                 }
43092             };
43093
43094             this.items.each(findMatchingField);
43095         }
43096         return field || null;
43097     },
43098
43099
43100     
43101     markInvalid : function(errors){
43102         if (Ext.isArray(errors)) {
43103             for(var i = 0, len = errors.length; i < len; i++){
43104                 var fieldError = errors[i];
43105                 var f = this.findField(fieldError.id);
43106                 if(f){
43107                     f.markInvalid(fieldError.msg);
43108                 }
43109             }
43110         } else {
43111             var field, id;
43112             for(id in errors){
43113                 if(!Ext.isFunction(errors[id]) && (field = this.findField(id))){
43114                     field.markInvalid(errors[id]);
43115                 }
43116             }
43117         }
43118
43119         return this;
43120     },
43121
43122     
43123     setValues : function(values){
43124         if(Ext.isArray(values)){ 
43125             for(var i = 0, len = values.length; i < len; i++){
43126                 var v = values[i];
43127                 var f = this.findField(v.id);
43128                 if(f){
43129                     f.setValue(v.value);
43130                     if(this.trackResetOnLoad){
43131                         f.originalValue = f.getValue();
43132                     }
43133                 }
43134             }
43135         }else{ 
43136             var field, id;
43137             for(id in values){
43138                 if(!Ext.isFunction(values[id]) && (field = this.findField(id))){
43139                     field.setValue(values[id]);
43140                     if(this.trackResetOnLoad){
43141                         field.originalValue = field.getValue();
43142                     }
43143                 }
43144             }
43145         }
43146         return this;
43147     },
43148
43149     
43150     getValues : function(asString){
43151         var fs = Ext.lib.Ajax.serializeForm(this.el.dom);
43152         if(asString === true){
43153             return fs;
43154         }
43155         return Ext.urlDecode(fs);
43156     },
43157
43158     
43159     getFieldValues : function(dirtyOnly){
43160         var o = {},
43161             n,
43162             key,
43163             val;
43164         this.items.each(function(f) {
43165             if (!f.disabled && (dirtyOnly !== true || f.isDirty())) {
43166                 n = f.getName();
43167                 key = o[n];
43168                 val = f.getValue();
43169
43170                 if(Ext.isDefined(key)){
43171                     if(Ext.isArray(key)){
43172                         o[n].push(val);
43173                     }else{
43174                         o[n] = [key, val];
43175                     }
43176                 }else{
43177                     o[n] = val;
43178                 }
43179             }
43180         });
43181         return o;
43182     },
43183
43184     
43185     clearInvalid : function(){
43186         this.items.each(function(f){
43187            f.clearInvalid();
43188         });
43189         return this;
43190     },
43191
43192     
43193     reset : function(){
43194         this.items.each(function(f){
43195             f.reset();
43196         });
43197         return this;
43198     },
43199
43200     
43201     add : function(){
43202         this.items.addAll(Array.prototype.slice.call(arguments, 0));
43203         return this;
43204     },
43205
43206     
43207     remove : function(field){
43208         this.items.remove(field);
43209         return this;
43210     },
43211
43212     
43213     cleanDestroyed : function() {
43214         this.items.filterBy(function(o) { return !!o.isDestroyed; }).each(this.remove, this);
43215     },
43216
43217     
43218     render : function(){
43219         this.items.each(function(f){
43220             if(f.isFormField && !f.rendered && document.getElementById(f.id)){ 
43221                 f.applyToMarkup(f.id);
43222             }
43223         });
43224         return this;
43225     },
43226
43227     
43228     applyToFields : function(o){
43229         this.items.each(function(f){
43230            Ext.apply(f, o);
43231         });
43232         return this;
43233     },
43234
43235     
43236     applyIfToFields : function(o){
43237         this.items.each(function(f){
43238            Ext.applyIf(f, o);
43239         });
43240         return this;
43241     },
43242
43243     callFieldMethod : function(fnName, args){
43244         args = args || [];
43245         this.items.each(function(f){
43246             if(Ext.isFunction(f[fnName])){
43247                 f[fnName].apply(f, args);
43248             }
43249         });
43250         return this;
43251     }
43252 });
43253
43254
43255 Ext.BasicForm = Ext.form.BasicForm;
43256
43257 Ext.FormPanel = Ext.extend(Ext.Panel, {
43258     
43259     
43260     
43261     
43262     
43263     
43264     
43265
43266
43267     
43268     minButtonWidth : 75,
43269
43270     
43271     labelAlign : 'left',
43272
43273     
43274     monitorValid : false,
43275
43276     
43277     monitorPoll : 200,
43278
43279     
43280     layout : 'form',
43281
43282     
43283     initComponent : function(){
43284         this.form = this.createForm();
43285         Ext.FormPanel.superclass.initComponent.call(this);
43286
43287         this.bodyCfg = {
43288             tag: 'form',
43289             cls: this.baseCls + '-body',
43290             method : this.method || 'POST',
43291             id : this.formId || Ext.id()
43292         };
43293         if(this.fileUpload) {
43294             this.bodyCfg.enctype = 'multipart/form-data';
43295         }
43296         this.initItems();
43297
43298         this.addEvents(
43299             
43300             'clientvalidation'
43301         );
43302
43303         this.relayEvents(this.form, ['beforeaction', 'actionfailed', 'actioncomplete']);
43304     },
43305
43306     
43307     createForm : function(){
43308         var config = Ext.applyIf({listeners: {}}, this.initialConfig);
43309         return new Ext.form.BasicForm(null, config);
43310     },
43311
43312     
43313     initFields : function(){
43314         var f = this.form;
43315         var formPanel = this;
43316         var fn = function(c){
43317             if(formPanel.isField(c)){
43318                 f.add(c);
43319             }else if(c.findBy && c != formPanel){
43320                 formPanel.applySettings(c);
43321                 
43322                 if(c.items && c.items.each){
43323                     c.items.each(fn, this);
43324                 }
43325             }
43326         };
43327         this.items.each(fn, this);
43328     },
43329
43330     
43331     applySettings: function(c){
43332         var ct = c.ownerCt;
43333         Ext.applyIf(c, {
43334             labelAlign: ct.labelAlign,
43335             labelWidth: ct.labelWidth,
43336             itemCls: ct.itemCls
43337         });
43338     },
43339
43340     
43341     getLayoutTarget : function(){
43342         return this.form.el;
43343     },
43344
43345     
43346     getForm : function(){
43347         return this.form;
43348     },
43349
43350     
43351     onRender : function(ct, position){
43352         this.initFields();
43353         Ext.FormPanel.superclass.onRender.call(this, ct, position);
43354         this.form.initEl(this.body);
43355     },
43356
43357     
43358     beforeDestroy : function(){
43359         this.stopMonitoring();
43360         this.form.destroy(true);
43361         Ext.FormPanel.superclass.beforeDestroy.call(this);
43362     },
43363
43364     
43365     isField : function(c) {
43366         return !!c.setValue && !!c.getValue && !!c.markInvalid && !!c.clearInvalid;
43367     },
43368
43369     
43370     initEvents : function(){
43371         Ext.FormPanel.superclass.initEvents.call(this);
43372         
43373         this.on({
43374             scope: this,
43375             add: this.onAddEvent,
43376             remove: this.onRemoveEvent
43377         });
43378         if(this.monitorValid){ 
43379             this.startMonitoring();
43380         }
43381     },
43382
43383     
43384     onAdd: function(c){
43385         Ext.FormPanel.superclass.onAdd.call(this, c);
43386         this.processAdd(c);
43387     },
43388
43389     
43390     onAddEvent: function(ct, c){
43391         if(ct !== this){
43392             this.processAdd(c);
43393         }
43394     },
43395
43396     
43397     processAdd : function(c){
43398         
43399         if(this.isField(c)){
43400             this.form.add(c);
43401         
43402         }else if(c.findBy){
43403             this.applySettings(c);
43404             this.form.add.apply(this.form, c.findBy(this.isField));
43405         }
43406     },
43407
43408     
43409     onRemove: function(c){
43410         Ext.FormPanel.superclass.onRemove.call(this, c);
43411         this.processRemove(c);
43412     },
43413
43414     onRemoveEvent: function(ct, c){
43415         if(ct !== this){
43416             this.processRemove(c);
43417         }
43418     },
43419
43420     
43421     processRemove: function(c){
43422         if(!this.destroying){
43423             
43424             if(this.isField(c)){
43425                 this.form.remove(c);
43426             
43427             }else if (c.findBy){
43428                 Ext.each(c.findBy(this.isField), this.form.remove, this.form);
43429                 
43430                 this.form.cleanDestroyed();
43431             }
43432         }
43433     },
43434
43435     
43436     startMonitoring : function(){
43437         if(!this.validTask){
43438             this.validTask = new Ext.util.TaskRunner();
43439             this.validTask.start({
43440                 run : this.bindHandler,
43441                 interval : this.monitorPoll || 200,
43442                 scope: this
43443             });
43444         }
43445     },
43446
43447     
43448     stopMonitoring : function(){
43449         if(this.validTask){
43450             this.validTask.stopAll();
43451             this.validTask = null;
43452         }
43453     },
43454
43455     
43456     load : function(){
43457         this.form.load.apply(this.form, arguments);
43458     },
43459
43460     
43461     onDisable : function(){
43462         Ext.FormPanel.superclass.onDisable.call(this);
43463         if(this.form){
43464             this.form.items.each(function(){
43465                  this.disable();
43466             });
43467         }
43468     },
43469
43470     
43471     onEnable : function(){
43472         Ext.FormPanel.superclass.onEnable.call(this);
43473         if(this.form){
43474             this.form.items.each(function(){
43475                  this.enable();
43476             });
43477         }
43478     },
43479
43480     
43481     bindHandler : function(){
43482         var valid = true;
43483         this.form.items.each(function(f){
43484             if(!f.isValid(true)){
43485                 valid = false;
43486                 return false;
43487             }
43488         });
43489         if(this.fbar){
43490             var fitems = this.fbar.items.items;
43491             for(var i = 0, len = fitems.length; i < len; i++){
43492                 var btn = fitems[i];
43493                 if(btn.formBind === true && btn.disabled === valid){
43494                     btn.setDisabled(!valid);
43495                 }
43496             }
43497         }
43498         this.fireEvent('clientvalidation', this, valid);
43499     }
43500 });
43501 Ext.reg('form', Ext.FormPanel);
43502
43503 Ext.form.FormPanel = Ext.FormPanel;
43504
43505 Ext.form.FieldSet = Ext.extend(Ext.Panel, {
43506     
43507     
43508     
43509     
43510     
43511     
43512     baseCls : 'x-fieldset',
43513     
43514     layout : 'form',
43515     
43516     animCollapse : false,
43517
43518     
43519     onRender : function(ct, position){
43520         if(!this.el){
43521             this.el = document.createElement('fieldset');
43522             this.el.id = this.id;
43523             if (this.title || this.header || this.checkboxToggle) {
43524                 this.el.appendChild(document.createElement('legend')).className = this.baseCls + '-header';
43525             }
43526         }
43527
43528         Ext.form.FieldSet.superclass.onRender.call(this, ct, position);
43529
43530         if(this.checkboxToggle){
43531             var o = typeof this.checkboxToggle == 'object' ?
43532                     this.checkboxToggle :
43533                     {tag: 'input', type: 'checkbox', name: this.checkboxName || this.id+'-checkbox'};
43534             this.checkbox = this.header.insertFirst(o);
43535             this.checkbox.dom.checked = !this.collapsed;
43536             this.mon(this.checkbox, 'click', this.onCheckClick, this);
43537         }
43538     },
43539
43540     
43541     onCollapse : function(doAnim, animArg){
43542         if(this.checkbox){
43543             this.checkbox.dom.checked = false;
43544         }
43545         Ext.form.FieldSet.superclass.onCollapse.call(this, doAnim, animArg);
43546
43547     },
43548
43549     
43550     onExpand : function(doAnim, animArg){
43551         if(this.checkbox){
43552             this.checkbox.dom.checked = true;
43553         }
43554         Ext.form.FieldSet.superclass.onExpand.call(this, doAnim, animArg);
43555     },
43556
43557     
43558     onCheckClick : function(){
43559         this[this.checkbox.dom.checked ? 'expand' : 'collapse']();
43560     }
43561
43562     
43563     
43564     
43565     
43566     
43567     
43568     
43569     
43570     
43571     
43572     
43573     
43574     
43575     
43576     
43577     
43578     
43579     
43580     
43581     
43582     
43583     
43584     
43585     
43586     
43587     
43588     
43589     
43590     
43591     
43592     
43593     
43594     
43595     
43596 });
43597 Ext.reg('fieldset', Ext.form.FieldSet);
43598
43599 Ext.form.HtmlEditor = Ext.extend(Ext.form.Field, {
43600     
43601     enableFormat : true,
43602     
43603     enableFontSize : true,
43604     
43605     enableColors : true,
43606     
43607     enableAlignments : true,
43608     
43609     enableLists : true,
43610     
43611     enableSourceEdit : true,
43612     
43613     enableLinks : true,
43614     
43615     enableFont : true,
43616     
43617     createLinkText : 'Please enter the URL for the link:',
43618     
43619     defaultLinkValue : 'http:/'+'/',
43620     
43621     fontFamilies : [
43622         'Arial',
43623         'Courier New',
43624         'Tahoma',
43625         'Times New Roman',
43626         'Verdana'
43627     ],
43628     defaultFont: 'tahoma',
43629     
43630     defaultValue: (Ext.isOpera || Ext.isIE6) ? '&#160;' : '&#8203;',
43631
43632     
43633     actionMode: 'wrap',
43634     validationEvent : false,
43635     deferHeight: true,
43636     initialized : false,
43637     activated : false,
43638     sourceEditMode : false,
43639     onFocus : Ext.emptyFn,
43640     iframePad:3,
43641     hideMode:'offsets',
43642     defaultAutoCreate : {
43643         tag: "textarea",
43644         style:"width:500px;height:300px;",
43645         autocomplete: "off"
43646     },
43647
43648     
43649     initComponent : function(){
43650         this.addEvents(
43651             
43652             'initialize',
43653             
43654             'activate',
43655              
43656             'beforesync',
43657              
43658             'beforepush',
43659              
43660             'sync',
43661              
43662             'push',
43663              
43664             'editmodechange'
43665         );
43666         Ext.form.HtmlEditor.superclass.initComponent.call(this);
43667     },
43668
43669     
43670     createFontOptions : function(){
43671         var buf = [], fs = this.fontFamilies, ff, lc;
43672         for(var i = 0, len = fs.length; i< len; i++){
43673             ff = fs[i];
43674             lc = ff.toLowerCase();
43675             buf.push(
43676                 '<option value="',lc,'" style="font-family:',ff,';"',
43677                     (this.defaultFont == lc ? ' selected="true">' : '>'),
43678                     ff,
43679                 '</option>'
43680             );
43681         }
43682         return buf.join('');
43683     },
43684
43685     
43686     createToolbar : function(editor){
43687         var items = [];
43688         var tipsEnabled = Ext.QuickTips && Ext.QuickTips.isEnabled();
43689
43690
43691         function btn(id, toggle, handler){
43692             return {
43693                 itemId : id,
43694                 cls : 'x-btn-icon',
43695                 iconCls: 'x-edit-'+id,
43696                 enableToggle:toggle !== false,
43697                 scope: editor,
43698                 handler:handler||editor.relayBtnCmd,
43699                 clickEvent:'mousedown',
43700                 tooltip: tipsEnabled ? editor.buttonTips[id] || undefined : undefined,
43701                 overflowText: editor.buttonTips[id].title || undefined,
43702                 tabIndex:-1
43703             };
43704         }
43705
43706
43707         if(this.enableFont && !Ext.isSafari2){
43708             var fontSelectItem = new Ext.Toolbar.Item({
43709                autoEl: {
43710                     tag:'select',
43711                     cls:'x-font-select',
43712                     html: this.createFontOptions()
43713                }
43714             });
43715
43716             items.push(
43717                 fontSelectItem,
43718                 '-'
43719             );
43720         }
43721
43722         if(this.enableFormat){
43723             items.push(
43724                 btn('bold'),
43725                 btn('italic'),
43726                 btn('underline')
43727             );
43728         }
43729
43730         if(this.enableFontSize){
43731             items.push(
43732                 '-',
43733                 btn('increasefontsize', false, this.adjustFont),
43734                 btn('decreasefontsize', false, this.adjustFont)
43735             );
43736         }
43737
43738         if(this.enableColors){
43739             items.push(
43740                 '-', {
43741                     itemId:'forecolor',
43742                     cls:'x-btn-icon',
43743                     iconCls: 'x-edit-forecolor',
43744                     clickEvent:'mousedown',
43745                     tooltip: tipsEnabled ? editor.buttonTips.forecolor || undefined : undefined,
43746                     tabIndex:-1,
43747                     menu : new Ext.menu.ColorMenu({
43748                         allowReselect: true,
43749                         focus: Ext.emptyFn,
43750                         value:'000000',
43751                         plain:true,
43752                         listeners: {
43753                             scope: this,
43754                             select: function(cp, color){
43755                                 this.execCmd('forecolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
43756                                 this.deferFocus();
43757                             }
43758                         },
43759                         clickEvent:'mousedown'
43760                     })
43761                 }, {
43762                     itemId:'backcolor',
43763                     cls:'x-btn-icon',
43764                     iconCls: 'x-edit-backcolor',
43765                     clickEvent:'mousedown',
43766                     tooltip: tipsEnabled ? editor.buttonTips.backcolor || undefined : undefined,
43767                     tabIndex:-1,
43768                     menu : new Ext.menu.ColorMenu({
43769                         focus: Ext.emptyFn,
43770                         value:'FFFFFF',
43771                         plain:true,
43772                         allowReselect: true,
43773                         listeners: {
43774                             scope: this,
43775                             select: function(cp, color){
43776                                 if(Ext.isGecko){
43777                                     this.execCmd('useCSS', false);
43778                                     this.execCmd('hilitecolor', color);
43779                                     this.execCmd('useCSS', true);
43780                                     this.deferFocus();
43781                                 }else{
43782                                     this.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
43783                                     this.deferFocus();
43784                                 }
43785                             }
43786                         },
43787                         clickEvent:'mousedown'
43788                     })
43789                 }
43790             );
43791         }
43792
43793         if(this.enableAlignments){
43794             items.push(
43795                 '-',
43796                 btn('justifyleft'),
43797                 btn('justifycenter'),
43798                 btn('justifyright')
43799             );
43800         }
43801
43802         if(!Ext.isSafari2){
43803             if(this.enableLinks){
43804                 items.push(
43805                     '-',
43806                     btn('createlink', false, this.createLink)
43807                 );
43808             }
43809
43810             if(this.enableLists){
43811                 items.push(
43812                     '-',
43813                     btn('insertorderedlist'),
43814                     btn('insertunorderedlist')
43815                 );
43816             }
43817             if(this.enableSourceEdit){
43818                 items.push(
43819                     '-',
43820                     btn('sourceedit', true, function(btn){
43821                         this.toggleSourceEdit(!this.sourceEditMode);
43822                     })
43823                 );
43824             }
43825         }
43826
43827         
43828         var tb = new Ext.Toolbar({
43829             renderTo: this.wrap.dom.firstChild,
43830             items: items
43831         });
43832
43833         if (fontSelectItem) {
43834             this.fontSelect = fontSelectItem.el;
43835
43836             this.mon(this.fontSelect, 'change', function(){
43837                 var font = this.fontSelect.dom.value;
43838                 this.relayCmd('fontname', font);
43839                 this.deferFocus();
43840             }, this);
43841         }
43842
43843         
43844         this.mon(tb.el, 'click', function(e){
43845             e.preventDefault();
43846         });
43847
43848         this.tb = tb;
43849         this.tb.doLayout();
43850     },
43851
43852     onDisable: function(){
43853         this.wrap.mask();
43854         Ext.form.HtmlEditor.superclass.onDisable.call(this);
43855     },
43856
43857     onEnable: function(){
43858         this.wrap.unmask();
43859         Ext.form.HtmlEditor.superclass.onEnable.call(this);
43860     },
43861
43862     setReadOnly: function(readOnly){
43863
43864         Ext.form.HtmlEditor.superclass.setReadOnly.call(this, readOnly);
43865         if(this.initialized){
43866             if(Ext.isIE){
43867                 this.getEditorBody().contentEditable = !readOnly;
43868             }else{
43869                 this.setDesignMode(!readOnly);
43870             }
43871             var bd = this.getEditorBody();
43872             if(bd){
43873                 bd.style.cursor = this.readOnly ? 'default' : 'text';
43874             }
43875             this.disableItems(readOnly);
43876         }
43877     },
43878
43879     
43880     getDocMarkup : function(){
43881         var h = Ext.fly(this.iframe).getHeight() - this.iframePad * 2;
43882         return String.format('<html><head><style type="text/css">body{border: 0; margin: 0; padding: {0}px; height: {1}px; cursor: text}</style></head><body></body></html>', this.iframePad, h);
43883     },
43884
43885     
43886     getEditorBody : function(){
43887         var doc = this.getDoc();
43888         return doc.body || doc.documentElement;
43889     },
43890
43891     
43892     getDoc : function(){
43893         return Ext.isIE ? this.getWin().document : (this.iframe.contentDocument || this.getWin().document);
43894     },
43895
43896     
43897     getWin : function(){
43898         return Ext.isIE ? this.iframe.contentWindow : window.frames[this.iframe.name];
43899     },
43900
43901     
43902     onRender : function(ct, position){
43903         Ext.form.HtmlEditor.superclass.onRender.call(this, ct, position);
43904         this.el.dom.style.border = '0 none';
43905         this.el.dom.setAttribute('tabIndex', -1);
43906         this.el.addClass('x-hidden');
43907         if(Ext.isIE){ 
43908             this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;');
43909         }
43910         this.wrap = this.el.wrap({
43911             cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
43912         });
43913
43914         this.createToolbar(this);
43915
43916         this.disableItems(true);
43917
43918         this.tb.doLayout();
43919
43920         this.createIFrame();
43921
43922         if(!this.width){
43923             var sz = this.el.getSize();
43924             this.setSize(sz.width, this.height || sz.height);
43925         }
43926         this.resizeEl = this.positionEl = this.wrap;
43927     },
43928
43929     createIFrame: function(){
43930         var iframe = document.createElement('iframe');
43931         iframe.name = Ext.id();
43932         iframe.frameBorder = '0';
43933         iframe.style.overflow = 'auto';
43934         iframe.src = Ext.SSL_SECURE_URL;
43935
43936         this.wrap.dom.appendChild(iframe);
43937         this.iframe = iframe;
43938
43939         this.monitorTask = Ext.TaskMgr.start({
43940             run: this.checkDesignMode,
43941             scope: this,
43942             interval:100
43943         });
43944     },
43945
43946     initFrame : function(){
43947         Ext.TaskMgr.stop(this.monitorTask);
43948         var doc = this.getDoc();
43949         this.win = this.getWin();
43950
43951         doc.open();
43952         doc.write(this.getDocMarkup());
43953         doc.close();
43954
43955         var task = { 
43956             run : function(){
43957                 var doc = this.getDoc();
43958                 if(doc.body || doc.readyState == 'complete'){
43959                     Ext.TaskMgr.stop(task);
43960                     this.setDesignMode(true);
43961                     this.initEditor.defer(10, this);
43962                 }
43963             },
43964             interval : 10,
43965             duration:10000,
43966             scope: this
43967         };
43968         Ext.TaskMgr.start(task);
43969     },
43970
43971
43972     checkDesignMode : function(){
43973         if(this.wrap && this.wrap.dom.offsetWidth){
43974             var doc = this.getDoc();
43975             if(!doc){
43976                 return;
43977             }
43978             if(!doc.editorInitialized || this.getDesignMode() != 'on'){
43979                 this.initFrame();
43980             }
43981         }
43982     },
43983
43984     
43985     setDesignMode : function(mode){
43986         var doc = this.getDoc();
43987         if (doc) {
43988             if(this.readOnly){
43989                 mode = false;
43990             }
43991             doc.designMode = (/on|true/i).test(String(mode).toLowerCase()) ?'on':'off';
43992         }
43993
43994     },
43995
43996     
43997     getDesignMode : function(){
43998         var doc = this.getDoc();
43999         if(!doc){ return ''; }
44000         return String(doc.designMode).toLowerCase();
44001
44002     },
44003
44004     disableItems: function(disabled){
44005         if(this.fontSelect){
44006             this.fontSelect.dom.disabled = disabled;
44007         }
44008         this.tb.items.each(function(item){
44009             if(item.getItemId() != 'sourceedit'){
44010                 item.setDisabled(disabled);
44011             }
44012         });
44013     },
44014
44015     
44016     onResize : function(w, h){
44017         Ext.form.HtmlEditor.superclass.onResize.apply(this, arguments);
44018         if(this.el && this.iframe){
44019             if(Ext.isNumber(w)){
44020                 var aw = w - this.wrap.getFrameWidth('lr');
44021                 this.el.setWidth(aw);
44022                 this.tb.setWidth(aw);
44023                 this.iframe.style.width = Math.max(aw, 0) + 'px';
44024             }
44025             if(Ext.isNumber(h)){
44026                 var ah = h - this.wrap.getFrameWidth('tb') - this.tb.el.getHeight();
44027                 this.el.setHeight(ah);
44028                 this.iframe.style.height = Math.max(ah, 0) + 'px';
44029                 var bd = this.getEditorBody();
44030                 if(bd){
44031                     bd.style.height = Math.max((ah - (this.iframePad*2)), 0) + 'px';
44032                 }
44033             }
44034         }
44035     },
44036
44037     
44038     toggleSourceEdit : function(sourceEditMode){
44039         var iframeHeight,
44040             elHeight;
44041
44042         if (sourceEditMode === undefined) {
44043             sourceEditMode = !this.sourceEditMode;
44044         }
44045         this.sourceEditMode = sourceEditMode === true;
44046         var btn = this.tb.getComponent('sourceedit');
44047
44048         if (btn.pressed !== this.sourceEditMode) {
44049             btn.toggle(this.sourceEditMode);
44050             if (!btn.xtbHidden) {
44051                 return;
44052             }
44053         }
44054         if (this.sourceEditMode) {
44055             
44056             this.previousSize = this.getSize();
44057
44058             iframeHeight = Ext.get(this.iframe).getHeight();
44059
44060             this.disableItems(true);
44061             this.syncValue();
44062             this.iframe.className = 'x-hidden';
44063             this.el.removeClass('x-hidden');
44064             this.el.dom.removeAttribute('tabIndex');
44065             this.el.focus();
44066             this.el.dom.style.height = iframeHeight + 'px';
44067         }
44068         else {
44069             elHeight = parseInt(this.el.dom.style.height, 10);
44070             if (this.initialized) {
44071                 this.disableItems(this.readOnly);
44072             }
44073             this.pushValue();
44074             this.iframe.className = '';
44075             this.el.addClass('x-hidden');
44076             this.el.dom.setAttribute('tabIndex', -1);
44077             this.deferFocus();
44078
44079             this.setSize(this.previousSize);
44080             delete this.previousSize;
44081             this.iframe.style.height = elHeight + 'px';
44082         }
44083         this.fireEvent('editmodechange', this, this.sourceEditMode);
44084     },
44085
44086     
44087     createLink : function() {
44088         var url = prompt(this.createLinkText, this.defaultLinkValue);
44089         if(url && url != 'http:/'+'/'){
44090             this.relayCmd('createlink', url);
44091         }
44092     },
44093
44094     
44095     initEvents : function(){
44096         this.originalValue = this.getValue();
44097     },
44098
44099     
44100     markInvalid : Ext.emptyFn,
44101
44102     
44103     clearInvalid : Ext.emptyFn,
44104
44105     
44106     setValue : function(v){
44107         Ext.form.HtmlEditor.superclass.setValue.call(this, v);
44108         this.pushValue();
44109         return this;
44110     },
44111
44112     
44113     cleanHtml: function(html) {
44114         html = String(html);
44115         if(Ext.isWebKit){ 
44116             html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
44117         }
44118
44119         
44120         if(html.charCodeAt(0) == this.defaultValue.replace(/\D/g, '')){
44121             html = html.substring(1);
44122         }
44123         return html;
44124     },
44125
44126     
44127     syncValue : function(){
44128         if(this.initialized){
44129             var bd = this.getEditorBody();
44130             var html = bd.innerHTML;
44131             if(Ext.isWebKit){
44132                 var bs = bd.getAttribute('style'); 
44133                 var m = bs.match(/text-align:(.*?);/i);
44134                 if(m && m[1]){
44135                     html = '<div style="'+m[0]+'">' + html + '</div>';
44136                 }
44137             }
44138             html = this.cleanHtml(html);
44139             if(this.fireEvent('beforesync', this, html) !== false){
44140                 this.el.dom.value = html;
44141                 this.fireEvent('sync', this, html);
44142             }
44143         }
44144     },
44145
44146     
44147     getValue : function() {
44148         this[this.sourceEditMode ? 'pushValue' : 'syncValue']();
44149         return Ext.form.HtmlEditor.superclass.getValue.call(this);
44150     },
44151
44152     
44153     pushValue : function(){
44154         if(this.initialized){
44155             var v = this.el.dom.value;
44156             if(!this.activated && v.length < 1){
44157                 v = this.defaultValue;
44158             }
44159             if(this.fireEvent('beforepush', this, v) !== false){
44160                 this.getEditorBody().innerHTML = v;
44161                 if(Ext.isGecko){
44162                     
44163                     this.setDesignMode(false);  
44164                     this.setDesignMode(true);
44165                 }
44166                 this.fireEvent('push', this, v);
44167             }
44168
44169         }
44170     },
44171
44172     
44173     deferFocus : function(){
44174         this.focus.defer(10, this);
44175     },
44176
44177     
44178     focus : function(){
44179         if(this.win && !this.sourceEditMode){
44180             this.win.focus();
44181         }else{
44182             this.el.focus();
44183         }
44184     },
44185
44186     
44187     initEditor : function(){
44188         
44189         try{
44190             var dbody = this.getEditorBody(),
44191                 ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat', 'background-color', 'color'),
44192                 doc,
44193                 fn;
44194
44195             ss['background-attachment'] = 'fixed'; 
44196             dbody.bgProperties = 'fixed'; 
44197
44198             Ext.DomHelper.applyStyles(dbody, ss);
44199
44200             doc = this.getDoc();
44201
44202             if(doc){
44203                 try{
44204                     Ext.EventManager.removeAll(doc);
44205                 }catch(e){}
44206             }
44207
44208             
44209             fn = this.onEditorEvent.createDelegate(this);
44210             Ext.EventManager.on(doc, {
44211                 mousedown: fn,
44212                 dblclick: fn,
44213                 click: fn,
44214                 keyup: fn,
44215                 buffer:100
44216             });
44217
44218             if(Ext.isGecko){
44219                 Ext.EventManager.on(doc, 'keypress', this.applyCommand, this);
44220             }
44221             if(Ext.isIE || Ext.isWebKit || Ext.isOpera){
44222                 Ext.EventManager.on(doc, 'keydown', this.fixKeys, this);
44223             }
44224             doc.editorInitialized = true;
44225             this.initialized = true;
44226             this.pushValue();
44227             this.setReadOnly(this.readOnly);
44228             this.fireEvent('initialize', this);
44229         }catch(e){}
44230     },
44231
44232     
44233     beforeDestroy : function(){
44234         if(this.monitorTask){
44235             Ext.TaskMgr.stop(this.monitorTask);
44236         }
44237         if(this.rendered){
44238             Ext.destroy(this.tb);
44239             var doc = this.getDoc();
44240             if(doc){
44241                 try{
44242                     Ext.EventManager.removeAll(doc);
44243                     for (var prop in doc){
44244                         delete doc[prop];
44245                     }
44246                 }catch(e){}
44247             }
44248             if(this.wrap){
44249                 this.wrap.dom.innerHTML = '';
44250                 this.wrap.remove();
44251             }
44252         }
44253         Ext.form.HtmlEditor.superclass.beforeDestroy.call(this);
44254     },
44255
44256     
44257     onFirstFocus : function(){
44258         this.activated = true;
44259         this.disableItems(this.readOnly);
44260         if(Ext.isGecko){ 
44261             this.win.focus();
44262             var s = this.win.getSelection();
44263             if(!s.focusNode || s.focusNode.nodeType != 3){
44264                 var r = s.getRangeAt(0);
44265                 r.selectNodeContents(this.getEditorBody());
44266                 r.collapse(true);
44267                 this.deferFocus();
44268             }
44269             try{
44270                 this.execCmd('useCSS', true);
44271                 this.execCmd('styleWithCSS', false);
44272             }catch(e){}
44273         }
44274         this.fireEvent('activate', this);
44275     },
44276
44277     
44278     adjustFont: function(btn){
44279         var adjust = btn.getItemId() == 'increasefontsize' ? 1 : -1,
44280             doc = this.getDoc(),
44281             v = parseInt(doc.queryCommandValue('FontSize') || 2, 10);
44282         if((Ext.isSafari && !Ext.isSafari2) || Ext.isChrome || Ext.isAir){
44283             
44284             
44285             if(v <= 10){
44286                 v = 1 + adjust;
44287             }else if(v <= 13){
44288                 v = 2 + adjust;
44289             }else if(v <= 16){
44290                 v = 3 + adjust;
44291             }else if(v <= 18){
44292                 v = 4 + adjust;
44293             }else if(v <= 24){
44294                 v = 5 + adjust;
44295             }else {
44296                 v = 6 + adjust;
44297             }
44298             v = v.constrain(1, 6);
44299         }else{
44300             if(Ext.isSafari){ 
44301                 adjust *= 2;
44302             }
44303             v = Math.max(1, v+adjust) + (Ext.isSafari ? 'px' : 0);
44304         }
44305         this.execCmd('FontSize', v);
44306     },
44307
44308     
44309     onEditorEvent : function(e){
44310         this.updateToolbar();
44311     },
44312
44313
44314     
44315     updateToolbar: function(){
44316
44317         if(this.readOnly){
44318             return;
44319         }
44320
44321         if(!this.activated){
44322             this.onFirstFocus();
44323             return;
44324         }
44325
44326         var btns = this.tb.items.map,
44327             doc = this.getDoc();
44328
44329         if(this.enableFont && !Ext.isSafari2){
44330             var name = (doc.queryCommandValue('FontName')||this.defaultFont).toLowerCase();
44331             if(name != this.fontSelect.dom.value){
44332                 this.fontSelect.dom.value = name;
44333             }
44334         }
44335         if(this.enableFormat){
44336             btns.bold.toggle(doc.queryCommandState('bold'));
44337             btns.italic.toggle(doc.queryCommandState('italic'));
44338             btns.underline.toggle(doc.queryCommandState('underline'));
44339         }
44340         if(this.enableAlignments){
44341             btns.justifyleft.toggle(doc.queryCommandState('justifyleft'));
44342             btns.justifycenter.toggle(doc.queryCommandState('justifycenter'));
44343             btns.justifyright.toggle(doc.queryCommandState('justifyright'));
44344         }
44345         if(!Ext.isSafari2 && this.enableLists){
44346             btns.insertorderedlist.toggle(doc.queryCommandState('insertorderedlist'));
44347             btns.insertunorderedlist.toggle(doc.queryCommandState('insertunorderedlist'));
44348         }
44349
44350         Ext.menu.MenuMgr.hideAll();
44351
44352         this.syncValue();
44353     },
44354
44355     
44356     relayBtnCmd : function(btn){
44357         this.relayCmd(btn.getItemId());
44358     },
44359
44360     
44361     relayCmd : function(cmd, value){
44362         (function(){
44363             this.focus();
44364             this.execCmd(cmd, value);
44365             this.updateToolbar();
44366         }).defer(10, this);
44367     },
44368
44369     
44370     execCmd : function(cmd, value){
44371         var doc = this.getDoc();
44372         doc.execCommand(cmd, false, value === undefined ? null : value);
44373         this.syncValue();
44374     },
44375
44376     
44377     applyCommand : function(e){
44378         if(e.ctrlKey){
44379             var c = e.getCharCode(), cmd;
44380             if(c > 0){
44381                 c = String.fromCharCode(c);
44382                 switch(c){
44383                     case 'b':
44384                         cmd = 'bold';
44385                     break;
44386                     case 'i':
44387                         cmd = 'italic';
44388                     break;
44389                     case 'u':
44390                         cmd = 'underline';
44391                     break;
44392                 }
44393                 if(cmd){
44394                     this.win.focus();
44395                     this.execCmd(cmd);
44396                     this.deferFocus();
44397                     e.preventDefault();
44398                 }
44399             }
44400         }
44401     },
44402
44403     
44404     insertAtCursor : function(text){
44405         if(!this.activated){
44406             return;
44407         }
44408         if(Ext.isIE){
44409             this.win.focus();
44410             var doc = this.getDoc(),
44411                 r = doc.selection.createRange();
44412             if(r){
44413                 r.pasteHTML(text);
44414                 this.syncValue();
44415                 this.deferFocus();
44416             }
44417         }else{
44418             this.win.focus();
44419             this.execCmd('InsertHTML', text);
44420             this.deferFocus();
44421         }
44422     },
44423
44424     
44425     fixKeys : function(){ 
44426         if(Ext.isIE){
44427             return function(e){
44428                 var k = e.getKey(),
44429                     doc = this.getDoc(),
44430                         r;
44431                 if(k == e.TAB){
44432                     e.stopEvent();
44433                     r = doc.selection.createRange();
44434                     if(r){
44435                         r.collapse(true);
44436                         r.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');
44437                         this.deferFocus();
44438                     }
44439                 }else if(k == e.ENTER){
44440                     r = doc.selection.createRange();
44441                     if(r){
44442                         var target = r.parentElement();
44443                         if(!target || target.tagName.toLowerCase() != 'li'){
44444                             e.stopEvent();
44445                             r.pasteHTML('<br />');
44446                             r.collapse(false);
44447                             r.select();
44448                         }
44449                     }
44450                 }
44451             };
44452         }else if(Ext.isOpera){
44453             return function(e){
44454                 var k = e.getKey();
44455                 if(k == e.TAB){
44456                     e.stopEvent();
44457                     this.win.focus();
44458                     this.execCmd('InsertHTML','&nbsp;&nbsp;&nbsp;&nbsp;');
44459                     this.deferFocus();
44460                 }
44461             };
44462         }else if(Ext.isWebKit){
44463             return function(e){
44464                 var k = e.getKey();
44465                 if(k == e.TAB){
44466                     e.stopEvent();
44467                     this.execCmd('InsertText','\t');
44468                     this.deferFocus();
44469                 }else if(k == e.ENTER){
44470                     e.stopEvent();
44471                     this.execCmd('InsertHtml','<br /><br />');
44472                     this.deferFocus();
44473                 }
44474              };
44475         }
44476     }(),
44477
44478     
44479     getToolbar : function(){
44480         return this.tb;
44481     },
44482
44483     
44484     buttonTips : {
44485         bold : {
44486             title: 'Bold (Ctrl+B)',
44487             text: 'Make the selected text bold.',
44488             cls: 'x-html-editor-tip'
44489         },
44490         italic : {
44491             title: 'Italic (Ctrl+I)',
44492             text: 'Make the selected text italic.',
44493             cls: 'x-html-editor-tip'
44494         },
44495         underline : {
44496             title: 'Underline (Ctrl+U)',
44497             text: 'Underline the selected text.',
44498             cls: 'x-html-editor-tip'
44499         },
44500         increasefontsize : {
44501             title: 'Grow Text',
44502             text: 'Increase the font size.',
44503             cls: 'x-html-editor-tip'
44504         },
44505         decreasefontsize : {
44506             title: 'Shrink Text',
44507             text: 'Decrease the font size.',
44508             cls: 'x-html-editor-tip'
44509         },
44510         backcolor : {
44511             title: 'Text Highlight Color',
44512             text: 'Change the background color of the selected text.',
44513             cls: 'x-html-editor-tip'
44514         },
44515         forecolor : {
44516             title: 'Font Color',
44517             text: 'Change the color of the selected text.',
44518             cls: 'x-html-editor-tip'
44519         },
44520         justifyleft : {
44521             title: 'Align Text Left',
44522             text: 'Align text to the left.',
44523             cls: 'x-html-editor-tip'
44524         },
44525         justifycenter : {
44526             title: 'Center Text',
44527             text: 'Center text in the editor.',
44528             cls: 'x-html-editor-tip'
44529         },
44530         justifyright : {
44531             title: 'Align Text Right',
44532             text: 'Align text to the right.',
44533             cls: 'x-html-editor-tip'
44534         },
44535         insertunorderedlist : {
44536             title: 'Bullet List',
44537             text: 'Start a bulleted list.',
44538             cls: 'x-html-editor-tip'
44539         },
44540         insertorderedlist : {
44541             title: 'Numbered List',
44542             text: 'Start a numbered list.',
44543             cls: 'x-html-editor-tip'
44544         },
44545         createlink : {
44546             title: 'Hyperlink',
44547             text: 'Make the selected text a hyperlink.',
44548             cls: 'x-html-editor-tip'
44549         },
44550         sourceedit : {
44551             title: 'Source Edit',
44552             text: 'Switch to source editing mode.',
44553             cls: 'x-html-editor-tip'
44554         }
44555     }
44556
44557     
44558     
44559     
44560     
44561     
44562     
44563     
44564     
44565     
44566     
44567     
44568     
44569     
44570     
44571     
44572     
44573     
44574     
44575     
44576     
44577     
44578     
44579     
44580     
44581     
44582     
44583     
44584     
44585     
44586     
44587     
44588     
44589     
44590     
44591 });
44592 Ext.reg('htmleditor', Ext.form.HtmlEditor);
44593
44594 Ext.form.TimeField = Ext.extend(Ext.form.ComboBox, {
44595     
44596     minValue : undefined,
44597     
44598     maxValue : undefined,
44599     
44600     minText : "The time in this field must be equal to or after {0}",
44601     
44602     maxText : "The time in this field must be equal to or before {0}",
44603     
44604     invalidText : "{0} is not a valid time",
44605     
44606     format : "g:i A",
44607     
44608     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",
44609     
44610     increment: 15,
44611
44612     
44613     mode: 'local',
44614     
44615     triggerAction: 'all',
44616     
44617     typeAhead: false,
44618
44619     
44620     
44621     
44622     initDate: '1/1/2008',
44623
44624     initDateFormat: 'j/n/Y',
44625
44626     
44627     initComponent : function(){
44628         if(Ext.isDefined(this.minValue)){
44629             this.setMinValue(this.minValue, true);
44630         }
44631         if(Ext.isDefined(this.maxValue)){
44632             this.setMaxValue(this.maxValue, true);
44633         }
44634         if(!this.store){
44635             this.generateStore(true);
44636         }
44637         Ext.form.TimeField.superclass.initComponent.call(this);
44638     },
44639
44640     
44641     setMinValue: function(value,  initial){
44642         this.setLimit(value, true, initial);
44643         return this;
44644     },
44645
44646     
44647     setMaxValue: function(value,  initial){
44648         this.setLimit(value, false, initial);
44649         return this;
44650     },
44651
44652     
44653     generateStore: function(initial){
44654         var min = this.minValue || new Date(this.initDate).clearTime(),
44655             max = this.maxValue || new Date(this.initDate).clearTime().add('mi', (24 * 60) - 1),
44656             times = [];
44657
44658         while(min <= max){
44659             times.push(min.dateFormat(this.format));
44660             min = min.add('mi', this.increment);
44661         }
44662         this.bindStore(times, initial);
44663     },
44664
44665     
44666     setLimit: function(value, isMin, initial){
44667         var d;
44668         if(Ext.isString(value)){
44669             d = this.parseDate(value);
44670         }else if(Ext.isDate(value)){
44671             d = value;
44672         }
44673         if(d){
44674             var val = new Date(this.initDate).clearTime();
44675             val.setHours(d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
44676             this[isMin ? 'minValue' : 'maxValue'] = val;
44677             if(!initial){
44678                 this.generateStore();
44679             }
44680         }
44681     },
44682
44683     
44684     getValue : function(){
44685         var v = Ext.form.TimeField.superclass.getValue.call(this);
44686         return this.formatDate(this.parseDate(v)) || '';
44687     },
44688
44689     
44690     setValue : function(value){
44691         return Ext.form.TimeField.superclass.setValue.call(this, this.formatDate(this.parseDate(value)));
44692     },
44693
44694     
44695     validateValue : Ext.form.DateField.prototype.validateValue,
44696
44697     formatDate : Ext.form.DateField.prototype.formatDate,
44698
44699     parseDate: function(value) {
44700         if (!value || Ext.isDate(value)) {
44701             return value;
44702         }
44703
44704         var id = this.initDate + ' ',
44705             idf = this.initDateFormat + ' ',
44706             v = Date.parseDate(id + value, idf + this.format), 
44707             af = this.altFormats;
44708
44709         if (!v && af) {
44710             if (!this.altFormatsArray) {
44711                 this.altFormatsArray = af.split("|");
44712             }
44713             for (var i = 0, afa = this.altFormatsArray, len = afa.length; i < len && !v; i++) {
44714                 v = Date.parseDate(id + value, idf + afa[i]);
44715             }
44716         }
44717
44718         return v;
44719     }
44720 });
44721 Ext.reg('timefield', Ext.form.TimeField);
44722 Ext.form.SliderField = Ext.extend(Ext.form.Field, {
44723     
44724     
44725     useTips : true,
44726     
44727     
44728     tipText : null,
44729     
44730     
44731     actionMode: 'wrap',
44732     
44733     
44734     initComponent : function() {
44735         var cfg = Ext.copyTo({
44736             id: this.id + '-slider'
44737         }, this.initialConfig, ['vertical', 'minValue', 'maxValue', 'decimalPrecision', 'keyIncrement', 'increment', 'clickToChange', 'animate']);
44738         
44739         
44740         if (this.useTips) {
44741             var plug = this.tipText ? {getText: this.tipText} : {};
44742             cfg.plugins = [new Ext.slider.Tip(plug)];
44743         }
44744         this.slider = new Ext.Slider(cfg);
44745         Ext.form.SliderField.superclass.initComponent.call(this);
44746     },    
44747     
44748     
44749     onRender : function(ct, position){
44750         this.autoCreate = {
44751             id: this.id,
44752             name: this.name,
44753             type: 'hidden',
44754             tag: 'input'    
44755         };
44756         Ext.form.SliderField.superclass.onRender.call(this, ct, position);
44757         this.wrap = this.el.wrap({cls: 'x-form-field-wrap'});
44758         this.resizeEl = this.positionEl = this.wrap;
44759         this.slider.render(this.wrap);
44760     },
44761     
44762     
44763     onResize : function(w, h, aw, ah){
44764         Ext.form.SliderField.superclass.onResize.call(this, w, h, aw, ah);
44765         this.slider.setSize(w, h);    
44766     },
44767     
44768     
44769     initEvents : function(){
44770         Ext.form.SliderField.superclass.initEvents.call(this);
44771         this.slider.on('change', this.onChange, this);   
44772     },
44773     
44774     
44775     onChange : function(slider, v){
44776         this.setValue(v, undefined, true);
44777     },
44778     
44779     
44780     onEnable : function(){
44781         Ext.form.SliderField.superclass.onEnable.call(this);
44782         this.slider.enable();
44783     },
44784     
44785     
44786     onDisable : function(){
44787         Ext.form.SliderField.superclass.onDisable.call(this);
44788         this.slider.disable();    
44789     },
44790     
44791     
44792     beforeDestroy : function(){
44793         Ext.destroy(this.slider);
44794         Ext.form.SliderField.superclass.beforeDestroy.call(this);
44795     },
44796     
44797     
44798     alignErrorIcon : function(){
44799         this.errorIcon.alignTo(this.slider.el, 'tl-tr', [2, 0]);
44800     },
44801     
44802     
44803     setMinValue : function(v){
44804         this.slider.setMinValue(v);
44805         return this;    
44806     },
44807     
44808     
44809     setMaxValue : function(v){
44810         this.slider.setMaxValue(v);
44811         return this;    
44812     },
44813     
44814     
44815     setValue : function(v, animate,  silent){
44816         
44817         
44818         if(!silent){
44819             this.slider.setValue(v, animate);
44820         }
44821         return Ext.form.SliderField.superclass.setValue.call(this, this.slider.getValue());
44822     },
44823     
44824     
44825     getValue : function(){
44826         return this.slider.getValue();    
44827     }
44828 });
44829
44830 Ext.reg('sliderfield', Ext.form.SliderField);
44831 Ext.form.Label = Ext.extend(Ext.BoxComponent, {
44832     
44833     
44834     
44835
44836     
44837     onRender : function(ct, position){
44838         if(!this.el){
44839             this.el = document.createElement('label');
44840             this.el.id = this.getId();
44841             this.el.innerHTML = this.text ? Ext.util.Format.htmlEncode(this.text) : (this.html || '');
44842             if(this.forId){
44843                 this.el.setAttribute('for', this.forId);
44844             }
44845         }
44846         Ext.form.Label.superclass.onRender.call(this, ct, position);
44847     },
44848
44849     
44850     setText : function(t, encode){
44851         var e = encode === false;
44852         this[!e ? 'text' : 'html'] = t;
44853         delete this[e ? 'text' : 'html'];
44854         if(this.rendered){
44855             this.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(t) : t;
44856         }
44857         return this;
44858     }
44859 });
44860
44861 Ext.reg('label', Ext.form.Label);
44862 Ext.form.Action = function(form, options){
44863     this.form = form;
44864     this.options = options || {};
44865 };
44866
44867
44868 Ext.form.Action.CLIENT_INVALID = 'client';
44869
44870 Ext.form.Action.SERVER_INVALID = 'server';
44871
44872 Ext.form.Action.CONNECT_FAILURE = 'connect';
44873
44874 Ext.form.Action.LOAD_FAILURE = 'load';
44875
44876 Ext.form.Action.prototype = {
44877
44878
44879
44880
44881
44882
44883
44884
44885
44886
44887
44888
44889
44890
44891     type : 'default',
44892
44893  
44894  
44895
44896     
44897     run : function(options){
44898
44899     },
44900
44901     
44902     success : function(response){
44903
44904     },
44905
44906     
44907     handleResponse : function(response){
44908
44909     },
44910
44911     
44912     failure : function(response){
44913         this.response = response;
44914         this.failureType = Ext.form.Action.CONNECT_FAILURE;
44915         this.form.afterAction(this, false);
44916     },
44917
44918     
44919     
44920     
44921     processResponse : function(response){
44922         this.response = response;
44923         if(!response.responseText && !response.responseXML){
44924             return true;
44925         }
44926         this.result = this.handleResponse(response);
44927         return this.result;
44928     },
44929
44930     
44931     getUrl : function(appendParams){
44932         var url = this.options.url || this.form.url || this.form.el.dom.action;
44933         if(appendParams){
44934             var p = this.getParams();
44935             if(p){
44936                 url = Ext.urlAppend(url, p);
44937             }
44938         }
44939         return url;
44940     },
44941
44942     
44943     getMethod : function(){
44944         return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
44945     },
44946
44947     
44948     getParams : function(){
44949         var bp = this.form.baseParams;
44950         var p = this.options.params;
44951         if(p){
44952             if(typeof p == "object"){
44953                 p = Ext.urlEncode(Ext.applyIf(p, bp));
44954             }else if(typeof p == 'string' && bp){
44955                 p += '&' + Ext.urlEncode(bp);
44956             }
44957         }else if(bp){
44958             p = Ext.urlEncode(bp);
44959         }
44960         return p;
44961     },
44962
44963     
44964     createCallback : function(opts){
44965         var opts = opts || {};
44966         return {
44967             success: this.success,
44968             failure: this.failure,
44969             scope: this,
44970             timeout: (opts.timeout*1000) || (this.form.timeout*1000),
44971             upload: this.form.fileUpload ? this.success : undefined
44972         };
44973     }
44974 };
44975
44976
44977 Ext.form.Action.Submit = function(form, options){
44978     Ext.form.Action.Submit.superclass.constructor.call(this, form, options);
44979 };
44980
44981 Ext.extend(Ext.form.Action.Submit, Ext.form.Action, {
44982     
44983     
44984     type : 'submit',
44985
44986     
44987     run : function(){
44988         var o = this.options,
44989             method = this.getMethod(),
44990             isGet = method == 'GET';
44991         if(o.clientValidation === false || this.form.isValid()){
44992             if (o.submitEmptyText === false) {
44993                 var fields = this.form.items,
44994                     emptyFields = [],
44995                     setupEmptyFields = function(f){
44996                         if (f.el.getValue() == f.emptyText) {
44997                             emptyFields.push(f);
44998                             f.el.dom.value = "";
44999                         }
45000                         if(f.isComposite && f.rendered){
45001                             f.items.each(setupEmptyFields);
45002                         }
45003                     };
45004                     
45005                 fields.each(setupEmptyFields);
45006             }
45007             Ext.Ajax.request(Ext.apply(this.createCallback(o), {
45008                 form:this.form.el.dom,
45009                 url:this.getUrl(isGet),
45010                 method: method,
45011                 headers: o.headers,
45012                 params:!isGet ? this.getParams() : null,
45013                 isUpload: this.form.fileUpload
45014             }));
45015             if (o.submitEmptyText === false) {
45016                 Ext.each(emptyFields, function(f) {
45017                     if (f.applyEmptyText) {
45018                         f.applyEmptyText();
45019                     }
45020                 });
45021             }
45022         }else if (o.clientValidation !== false){ 
45023             this.failureType = Ext.form.Action.CLIENT_INVALID;
45024             this.form.afterAction(this, false);
45025         }
45026     },
45027
45028     
45029     success : function(response){
45030         var result = this.processResponse(response);
45031         if(result === true || result.success){
45032             this.form.afterAction(this, true);
45033             return;
45034         }
45035         if(result.errors){
45036             this.form.markInvalid(result.errors);
45037         }
45038         this.failureType = Ext.form.Action.SERVER_INVALID;
45039         this.form.afterAction(this, false);
45040     },
45041
45042     
45043     handleResponse : function(response){
45044         if(this.form.errorReader){
45045             var rs = this.form.errorReader.read(response);
45046             var errors = [];
45047             if(rs.records){
45048                 for(var i = 0, len = rs.records.length; i < len; i++) {
45049                     var r = rs.records[i];
45050                     errors[i] = r.data;
45051                 }
45052             }
45053             if(errors.length < 1){
45054                 errors = null;
45055             }
45056             return {
45057                 success : rs.success,
45058                 errors : errors
45059             };
45060         }
45061         return Ext.decode(response.responseText);
45062     }
45063 });
45064
45065
45066
45067 Ext.form.Action.Load = function(form, options){
45068     Ext.form.Action.Load.superclass.constructor.call(this, form, options);
45069     this.reader = this.form.reader;
45070 };
45071
45072 Ext.extend(Ext.form.Action.Load, Ext.form.Action, {
45073     
45074     type : 'load',
45075
45076     
45077     run : function(){
45078         Ext.Ajax.request(Ext.apply(
45079                 this.createCallback(this.options), {
45080                     method:this.getMethod(),
45081                     url:this.getUrl(false),
45082                     headers: this.options.headers,
45083                     params:this.getParams()
45084         }));
45085     },
45086
45087     
45088     success : function(response){
45089         var result = this.processResponse(response);
45090         if(result === true || !result.success || !result.data){
45091             this.failureType = Ext.form.Action.LOAD_FAILURE;
45092             this.form.afterAction(this, false);
45093             return;
45094         }
45095         this.form.clearInvalid();
45096         this.form.setValues(result.data);
45097         this.form.afterAction(this, true);
45098     },
45099
45100     
45101     handleResponse : function(response){
45102         if(this.form.reader){
45103             var rs = this.form.reader.read(response);
45104             var data = rs.records && rs.records[0] ? rs.records[0].data : null;
45105             return {
45106                 success : rs.success,
45107                 data : data
45108             };
45109         }
45110         return Ext.decode(response.responseText);
45111     }
45112 });
45113
45114
45115
45116
45117 Ext.form.Action.DirectLoad = Ext.extend(Ext.form.Action.Load, {
45118     constructor: function(form, opts) {
45119         Ext.form.Action.DirectLoad.superclass.constructor.call(this, form, opts);
45120     },
45121     type : 'directload',
45122
45123     run : function(){
45124         var args = this.getParams();
45125         args.push(this.success, this);
45126         this.form.api.load.apply(window, args);
45127     },
45128
45129     getParams : function() {
45130         var buf = [], o = {};
45131         var bp = this.form.baseParams;
45132         var p = this.options.params;
45133         Ext.apply(o, p, bp);
45134         var paramOrder = this.form.paramOrder;
45135         if(paramOrder){
45136             for(var i = 0, len = paramOrder.length; i < len; i++){
45137                 buf.push(o[paramOrder[i]]);
45138             }
45139         }else if(this.form.paramsAsHash){
45140             buf.push(o);
45141         }
45142         return buf;
45143     },
45144     
45145     
45146     
45147     processResponse : function(result) {
45148         this.result = result;
45149         return result;
45150     },
45151
45152     success : function(response, trans){
45153         if(trans.type == Ext.Direct.exceptions.SERVER){
45154             response = {};
45155         }
45156         Ext.form.Action.DirectLoad.superclass.success.call(this, response);
45157     }
45158 });
45159
45160
45161 Ext.form.Action.DirectSubmit = Ext.extend(Ext.form.Action.Submit, {
45162     constructor : function(form, opts) {
45163         Ext.form.Action.DirectSubmit.superclass.constructor.call(this, form, opts);
45164     },
45165     type : 'directsubmit',
45166     
45167     run : function(){
45168         var o = this.options;
45169         if(o.clientValidation === false || this.form.isValid()){
45170             
45171             
45172             this.success.params = this.getParams();
45173             this.form.api.submit(this.form.el.dom, this.success, this);
45174         }else if (o.clientValidation !== false){ 
45175             this.failureType = Ext.form.Action.CLIENT_INVALID;
45176             this.form.afterAction(this, false);
45177         }
45178     },
45179
45180     getParams : function() {
45181         var o = {};
45182         var bp = this.form.baseParams;
45183         var p = this.options.params;
45184         Ext.apply(o, p, bp);
45185         return o;
45186     },
45187     
45188     
45189     
45190     processResponse : function(result) {
45191         this.result = result;
45192         return result;
45193     },
45194
45195     success : function(response, trans){
45196         if(trans.type == Ext.Direct.exceptions.SERVER){
45197             response = {};
45198         }
45199         Ext.form.Action.DirectSubmit.superclass.success.call(this, response);
45200     }
45201 });
45202
45203 Ext.form.Action.ACTION_TYPES = {
45204     'load' : Ext.form.Action.Load,
45205     'submit' : Ext.form.Action.Submit,
45206     'directload' : Ext.form.Action.DirectLoad,
45207     'directsubmit' : Ext.form.Action.DirectSubmit
45208 };
45209
45210 Ext.form.VTypes = function(){
45211     
45212     var alpha = /^[a-zA-Z_]+$/,
45213         alphanum = /^[a-zA-Z0-9_]+$/,
45214         email = /^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/,
45215         url = /(((^https?)|(^ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
45216
45217     
45218     return {
45219         
45220         'email' : function(v){
45221             return email.test(v);
45222         },
45223         
45224         'emailText' : 'This field should be an e-mail address in the format "user@example.com"',
45225         
45226         'emailMask' : /[a-z0-9_\.\-@\+]/i,
45227
45228         
45229         'url' : function(v){
45230             return url.test(v);
45231         },
45232         
45233         'urlText' : 'This field should be a URL in the format "http:/'+'/www.example.com"',
45234
45235         
45236         'alpha' : function(v){
45237             return alpha.test(v);
45238         },
45239         
45240         'alphaText' : 'This field should only contain letters and _',
45241         
45242         'alphaMask' : /[a-z_]/i,
45243
45244         
45245         'alphanum' : function(v){
45246             return alphanum.test(v);
45247         },
45248         
45249         'alphanumText' : 'This field should only contain letters, numbers and _',
45250         
45251         'alphanumMask' : /[a-z0-9_]/i
45252     };
45253 }();
45254
45255 Ext.grid.GridPanel = Ext.extend(Ext.Panel, {
45256     
45257     autoExpandColumn : false,
45258     
45259     
45260     autoExpandMax : 1000,
45261     
45262     
45263     autoExpandMin : 50,
45264     
45265     
45266     columnLines : false,
45267     
45268     
45269     
45270     
45271     
45272     
45273     ddText : '{0} selected row{1}',
45274     
45275     
45276     deferRowRender : true,
45277     
45278     
45279     
45280     
45281     enableColumnHide : true,
45282     
45283     
45284     enableColumnMove : true,
45285     
45286     
45287     enableDragDrop : false,
45288     
45289     
45290     enableHdMenu : true,
45291     
45292     
45293     
45294     loadMask : false,
45295     
45296     
45297     
45298     minColumnWidth : 25,
45299     
45300     
45301     
45302     
45303     
45304     stripeRows : false,
45305     
45306     
45307     trackMouseOver : true,
45308     
45309     
45310     stateEvents : ['columnmove', 'columnresize', 'sortchange', 'groupchange'],
45311     
45312     
45313     view : null,
45314
45315     
45316     bubbleEvents: [],
45317
45318     
45319
45320     
45321     rendered : false,
45322     
45323     
45324     viewReady : false,
45325
45326     
45327     initComponent : function() {
45328         Ext.grid.GridPanel.superclass.initComponent.call(this);
45329
45330         if (this.columnLines) {
45331             this.cls = (this.cls || '') + ' x-grid-with-col-lines';
45332         }
45333         
45334         
45335         this.autoScroll = false;
45336         this.autoWidth = false;
45337
45338         if(Ext.isArray(this.columns)){
45339             this.colModel = new Ext.grid.ColumnModel(this.columns);
45340             delete this.columns;
45341         }
45342
45343         
45344         if(this.ds){
45345             this.store = this.ds;
45346             delete this.ds;
45347         }
45348         if(this.cm){
45349             this.colModel = this.cm;
45350             delete this.cm;
45351         }
45352         if(this.sm){
45353             this.selModel = this.sm;
45354             delete this.sm;
45355         }
45356         this.store = Ext.StoreMgr.lookup(this.store);
45357
45358         this.addEvents(
45359             
45360             
45361             'click',
45362             
45363             'dblclick',
45364             
45365             'contextmenu',
45366             
45367             'mousedown',
45368             
45369             'mouseup',
45370             
45371             'mouseover',
45372             
45373             'mouseout',
45374             
45375             'keypress',
45376             
45377             'keydown',
45378
45379             
45380             
45381             'cellmousedown',
45382             
45383             'rowmousedown',
45384             
45385             'headermousedown',
45386
45387             
45388             'groupmousedown',
45389
45390             
45391             'rowbodymousedown',
45392
45393             
45394             'containermousedown',
45395
45396             
45397             'cellclick',
45398             
45399             'celldblclick',
45400             
45401             'rowclick',
45402             
45403             'rowdblclick',
45404             
45405             'headerclick',
45406             
45407             'headerdblclick',
45408             
45409             'groupclick',
45410             
45411             'groupdblclick',
45412             
45413             'containerclick',
45414             
45415             'containerdblclick',
45416
45417             
45418             'rowbodyclick',
45419             
45420             'rowbodydblclick',
45421
45422             
45423             'rowcontextmenu',
45424             
45425             'cellcontextmenu',
45426             
45427             'headercontextmenu',
45428             
45429             'groupcontextmenu',
45430             
45431             'containercontextmenu',
45432             
45433             'rowbodycontextmenu',
45434             
45435             'bodyscroll',
45436             
45437             'columnresize',
45438             
45439             'columnmove',
45440             
45441             'sortchange',
45442             
45443             'groupchange',
45444             
45445             'reconfigure',
45446             
45447             'viewready'
45448         );
45449     },
45450
45451     
45452     onRender : function(ct, position){
45453         Ext.grid.GridPanel.superclass.onRender.apply(this, arguments);
45454
45455         var c = this.getGridEl();
45456
45457         this.el.addClass('x-grid-panel');
45458
45459         this.mon(c, {
45460             scope: this,
45461             mousedown: this.onMouseDown,
45462             click: this.onClick,
45463             dblclick: this.onDblClick,
45464             contextmenu: this.onContextMenu
45465         });
45466
45467         this.relayEvents(c, ['mousedown','mouseup','mouseover','mouseout','keypress', 'keydown']);
45468
45469         var view = this.getView();
45470         view.init(this);
45471         view.render();
45472         this.getSelectionModel().init(this);
45473     },
45474
45475     
45476     initEvents : function(){
45477         Ext.grid.GridPanel.superclass.initEvents.call(this);
45478
45479         if(this.loadMask){
45480             this.loadMask = new Ext.LoadMask(this.bwrap,
45481                     Ext.apply({store:this.store}, this.loadMask));
45482         }
45483     },
45484
45485     initStateEvents : function(){
45486         Ext.grid.GridPanel.superclass.initStateEvents.call(this);
45487         this.mon(this.colModel, 'hiddenchange', this.saveState, this, {delay: 100});
45488     },
45489
45490     applyState : function(state){
45491         var cm = this.colModel,
45492             cs = state.columns,
45493             store = this.store,
45494             s,
45495             c,
45496             colIndex;
45497
45498         if(cs){
45499             for(var i = 0, len = cs.length; i < len; i++){
45500                 s = cs[i];
45501                 c = cm.getColumnById(s.id);
45502                 if(c){
45503                     colIndex = cm.getIndexById(s.id);
45504                     cm.setState(colIndex, {
45505                         hidden: s.hidden,
45506                         width: s.width,
45507                         sortable: s.sortable
45508                     });
45509                     if(colIndex != i){
45510                         cm.moveColumn(colIndex, i);
45511                     }
45512                 }
45513             }
45514         }
45515         if(store){
45516             s = state.sort;
45517             if(s){
45518                 store[store.remoteSort ? 'setDefaultSort' : 'sort'](s.field, s.direction);
45519             }
45520             s = state.group;
45521             if(store.groupBy){
45522                 if(s){
45523                     store.groupBy(s);
45524                 }else{
45525                     store.clearGrouping();
45526                 }
45527             }
45528
45529         }
45530         var o = Ext.apply({}, state);
45531         delete o.columns;
45532         delete o.sort;
45533         Ext.grid.GridPanel.superclass.applyState.call(this, o);
45534     },
45535
45536     getState : function(){
45537         var o = {columns: []},
45538             store = this.store,
45539             ss,
45540             gs;
45541
45542         for(var i = 0, c; (c = this.colModel.config[i]); i++){
45543             o.columns[i] = {
45544                 id: c.id,
45545                 width: c.width
45546             };
45547             if(c.hidden){
45548                 o.columns[i].hidden = true;
45549             }
45550             if(c.sortable){
45551                 o.columns[i].sortable = true;
45552             }
45553         }
45554         if(store){
45555             ss = store.getSortState();
45556             if(ss){
45557                 o.sort = ss;
45558             }
45559             if(store.getGroupState){
45560                 gs = store.getGroupState();
45561                 if(gs){
45562                     o.group = gs;
45563                 }
45564             }
45565         }
45566         return o;
45567     },
45568
45569     
45570     afterRender : function(){
45571         Ext.grid.GridPanel.superclass.afterRender.call(this);
45572         var v = this.view;
45573         this.on('bodyresize', v.layout, v);
45574         v.layout(true);
45575         if(this.deferRowRender){
45576             if (!this.deferRowRenderTask){
45577                 this.deferRowRenderTask = new Ext.util.DelayedTask(v.afterRender, this.view);
45578             }
45579             this.deferRowRenderTask.delay(10);
45580         }else{
45581             v.afterRender();
45582         }
45583         this.viewReady = true;
45584     },
45585
45586     
45587     reconfigure : function(store, colModel){
45588         var rendered = this.rendered;
45589         if(rendered){
45590             if(this.loadMask){
45591                 this.loadMask.destroy();
45592                 this.loadMask = new Ext.LoadMask(this.bwrap,
45593                         Ext.apply({}, {store:store}, this.initialConfig.loadMask));
45594             }
45595         }
45596         if(this.view){
45597             this.view.initData(store, colModel);
45598         }
45599         this.store = store;
45600         this.colModel = colModel;
45601         if(rendered){
45602             this.view.refresh(true);
45603         }
45604         this.fireEvent('reconfigure', this, store, colModel);
45605     },
45606
45607     
45608     onDestroy : function(){
45609         if (this.deferRowRenderTask && this.deferRowRenderTask.cancel){
45610             this.deferRowRenderTask.cancel();
45611         }
45612         if(this.rendered){
45613             Ext.destroy(this.view, this.loadMask);
45614         }else if(this.store && this.store.autoDestroy){
45615             this.store.destroy();
45616         }
45617         Ext.destroy(this.colModel, this.selModel);
45618         this.store = this.selModel = this.colModel = this.view = this.loadMask = null;
45619         Ext.grid.GridPanel.superclass.onDestroy.call(this);
45620     },
45621
45622     
45623     processEvent : function(name, e){
45624         this.view.processEvent(name, e);
45625     },
45626
45627     
45628     onClick : function(e){
45629         this.processEvent('click', e);
45630     },
45631
45632     
45633     onMouseDown : function(e){
45634         this.processEvent('mousedown', e);
45635     },
45636
45637     
45638     onContextMenu : function(e, t){
45639         this.processEvent('contextmenu', e);
45640     },
45641
45642     
45643     onDblClick : function(e){
45644         this.processEvent('dblclick', e);
45645     },
45646
45647     
45648     walkCells : function(row, col, step, fn, scope){
45649         var cm    = this.colModel,
45650             clen  = cm.getColumnCount(),
45651             ds    = this.store,
45652             rlen  = ds.getCount(),
45653             first = true;
45654
45655         if(step < 0){
45656             if(col < 0){
45657                 row--;
45658                 first = false;
45659             }
45660             while(row >= 0){
45661                 if(!first){
45662                     col = clen-1;
45663                 }
45664                 first = false;
45665                 while(col >= 0){
45666                     if(fn.call(scope || this, row, col, cm) === true){
45667                         return [row, col];
45668                     }
45669                     col--;
45670                 }
45671                 row--;
45672             }
45673         } else {
45674             if(col >= clen){
45675                 row++;
45676                 first = false;
45677             }
45678             while(row < rlen){
45679                 if(!first){
45680                     col = 0;
45681                 }
45682                 first = false;
45683                 while(col < clen){
45684                     if(fn.call(scope || this, row, col, cm) === true){
45685                         return [row, col];
45686                     }
45687                     col++;
45688                 }
45689                 row++;
45690             }
45691         }
45692         return null;
45693     },
45694
45695     
45696     getGridEl : function(){
45697         return this.body;
45698     },
45699
45700     
45701     stopEditing : Ext.emptyFn,
45702
45703     
45704     getSelectionModel : function(){
45705         if(!this.selModel){
45706             this.selModel = new Ext.grid.RowSelectionModel(
45707                     this.disableSelection ? {selectRow: Ext.emptyFn} : null);
45708         }
45709         return this.selModel;
45710     },
45711
45712     
45713     getStore : function(){
45714         return this.store;
45715     },
45716
45717     
45718     getColumnModel : function(){
45719         return this.colModel;
45720     },
45721
45722     
45723     getView : function() {
45724         if (!this.view) {
45725             this.view = new Ext.grid.GridView(this.viewConfig);
45726         }
45727         
45728         return this.view;
45729     },
45730     
45731     getDragDropText : function(){
45732         var count = this.selModel.getCount();
45733         return String.format(this.ddText, count, count == 1 ? '' : 's');
45734     }
45735
45736     
45737     
45738     
45739     
45740     
45741     
45742     
45743     
45744     
45745     
45746     
45747     
45748     
45749     
45750     
45751     
45752     
45753     
45754     
45755     
45756     
45757     
45758     
45759     
45760     
45761     
45762     
45763     
45764     
45765     
45766     
45767
45768
45769
45770     
45771     
45772     
45773     
45774     
45775     
45776     
45777     
45778     
45779     
45780     
45781     
45782     
45783     
45784     
45785     
45786 });
45787 Ext.reg('grid', Ext.grid.GridPanel);
45788 Ext.grid.PivotGrid = Ext.extend(Ext.grid.GridPanel, {
45789     
45790     
45791     aggregator: 'sum',
45792     
45793     
45794     renderer: undefined,
45795     
45796     
45797     
45798     
45799     
45800     
45801     
45802     
45803     initComponent: function() {
45804         Ext.grid.PivotGrid.superclass.initComponent.apply(this, arguments);
45805         
45806         this.initAxes();
45807         
45808         
45809         this.enableColumnResize = false;
45810         
45811         this.viewConfig = Ext.apply(this.viewConfig || {}, {
45812             forceFit: true
45813         });
45814         
45815         
45816         
45817         this.colModel = new Ext.grid.ColumnModel({});
45818     },
45819     
45820     
45821     getAggregator: function() {
45822         if (typeof this.aggregator == 'string') {
45823             return Ext.grid.PivotAggregatorMgr.types[this.aggregator];
45824         } else {
45825             return this.aggregator;
45826         }
45827     },
45828     
45829     
45830     setAggregator: function(aggregator) {
45831         this.aggregator = aggregator;
45832     },
45833     
45834     
45835     setMeasure: function(measure) {
45836         this.measure = measure;
45837     },
45838     
45839     
45840     setLeftAxis: function(axis, refresh) {
45841         
45842         this.leftAxis = axis;
45843         
45844         if (refresh) {
45845             this.view.refresh();
45846         }
45847     },
45848     
45849     
45850     setTopAxis: function(axis, refresh) {
45851         
45852         this.topAxis = axis;
45853         
45854         if (refresh) {
45855             this.view.refresh();
45856         }
45857     },
45858     
45859     
45860     initAxes: function() {
45861         var PivotAxis = Ext.grid.PivotAxis;
45862         
45863         if (!(this.leftAxis instanceof PivotAxis)) {
45864             this.setLeftAxis(new PivotAxis({
45865                 orientation: 'vertical',
45866                 dimensions : this.leftAxis || [],
45867                 store      : this.store
45868             }));
45869         };
45870         
45871         if (!(this.topAxis instanceof PivotAxis)) {
45872             this.setTopAxis(new PivotAxis({
45873                 orientation: 'horizontal',
45874                 dimensions : this.topAxis || [],
45875                 store      : this.store
45876             }));
45877         };
45878     },
45879     
45880     
45881     extractData: function() {
45882         var records  = this.store.data.items,
45883             recCount = records.length,
45884             cells    = [],
45885             record, i, j, k;
45886         
45887         if (recCount == 0) {
45888             return [];
45889         }
45890         
45891         var leftTuples = this.leftAxis.getTuples(),
45892             leftCount  = leftTuples.length,
45893             topTuples  = this.topAxis.getTuples(),
45894             topCount   = topTuples.length,
45895             aggregator = this.getAggregator();
45896         
45897         for (i = 0; i < recCount; i++) {
45898             record = records[i];
45899             
45900             for (j = 0; j < leftCount; j++) {
45901                 cells[j] = cells[j] || [];
45902                 
45903                 if (leftTuples[j].matcher(record) === true) {
45904                     for (k = 0; k < topCount; k++) {
45905                         cells[j][k] = cells[j][k] || [];
45906                         
45907                         if (topTuples[k].matcher(record)) {
45908                             cells[j][k].push(record);
45909                         }
45910                     }
45911                 }
45912             }
45913         }
45914         
45915         var rowCount = cells.length,
45916             colCount, row;
45917         
45918         for (i = 0; i < rowCount; i++) {
45919             row = cells[i];
45920             colCount = row.length;
45921             
45922             for (j = 0; j < colCount; j++) {
45923                 cells[i][j] = aggregator(cells[i][j], this.measure);
45924             }
45925         }
45926         
45927         return cells;
45928     },
45929     
45930     
45931     getView: function() {
45932         if (!this.view) {
45933             this.view = new Ext.grid.PivotGridView(this.viewConfig);
45934         }
45935         
45936         return this.view;
45937     }
45938 });
45939
45940 Ext.reg('pivotgrid', Ext.grid.PivotGrid);
45941
45942
45943 Ext.grid.PivotAggregatorMgr = new Ext.AbstractManager();
45944
45945 Ext.grid.PivotAggregatorMgr.registerType('sum', function(records, measure) {
45946     var length = records.length,
45947         total  = 0,
45948         i;
45949     
45950     for (i = 0; i < length; i++) {
45951         total += records[i].get(measure);
45952     }
45953     
45954     return total;
45955 });
45956
45957 Ext.grid.PivotAggregatorMgr.registerType('avg', function(records, measure) {
45958     var length = records.length,
45959         total  = 0,
45960         i;
45961     
45962     for (i = 0; i < length; i++) {
45963         total += records[i].get(measure);
45964     }
45965     
45966     return (total / length) || 'n/a';
45967 });
45968
45969 Ext.grid.PivotAggregatorMgr.registerType('min', function(records, measure) {
45970     var data   = [],
45971         length = records.length,
45972         i;
45973     
45974     for (i = 0; i < length; i++) {
45975         data.push(records[i].get(measure));
45976     }
45977     
45978     return Math.min.apply(this, data) || 'n/a';
45979 });
45980
45981 Ext.grid.PivotAggregatorMgr.registerType('max', function(records, measure) {
45982     var data   = [],
45983         length = records.length,
45984         i;
45985     
45986     for (i = 0; i < length; i++) {
45987         data.push(records[i].get(measure));
45988     }
45989     
45990     return Math.max.apply(this, data) || 'n/a';
45991 });
45992
45993 Ext.grid.PivotAggregatorMgr.registerType('count', function(records, measure) {
45994     return records.length;
45995 });
45996 Ext.grid.GridView = Ext.extend(Ext.util.Observable, {
45997     
45998
45999     
46000
46001     
46002
46003     
46004
46005     
46006
46007     
46008     deferEmptyText : true,
46009
46010     
46011     scrollOffset : undefined,
46012
46013     
46014     autoFill : false,
46015
46016     
46017     forceFit : false,
46018
46019     
46020     sortClasses : ['sort-asc', 'sort-desc'],
46021
46022     
46023     sortAscText : 'Sort Ascending',
46024
46025     
46026     sortDescText : 'Sort Descending',
46027
46028     
46029     columnsText : 'Columns',
46030
46031     
46032     selectedRowClass : 'x-grid3-row-selected',
46033
46034     
46035     borderWidth : 2,
46036     tdClass : 'x-grid3-cell',
46037     hdCls : 'x-grid3-hd',
46038     
46039     
46040     
46041     markDirty : true,
46042
46043     
46044     cellSelectorDepth : 4,
46045     
46046     
46047     rowSelectorDepth : 10,
46048
46049     
46050     rowBodySelectorDepth : 10,
46051
46052     
46053     cellSelector : 'td.x-grid3-cell',
46054     
46055     
46056     rowSelector : 'div.x-grid3-row',
46057
46058     
46059     rowBodySelector : 'div.x-grid3-row-body',
46060
46061     
46062     firstRowCls: 'x-grid3-row-first',
46063     lastRowCls: 'x-grid3-row-last',
46064     rowClsRe: /(?:^|\s+)x-grid3-row-(first|last|alt)(?:\s+|$)/g,
46065     
46066     
46067     headerMenuOpenCls: 'x-grid3-hd-menu-open',
46068     
46069     
46070     rowOverCls: 'x-grid3-row-over',
46071
46072     constructor : function(config) {
46073         Ext.apply(this, config);
46074         
46075         
46076         this.addEvents(
46077             
46078             'beforerowremoved',
46079             
46080             
46081             'beforerowsinserted',
46082             
46083             
46084             'beforerefresh',
46085             
46086             
46087             'rowremoved',
46088             
46089             
46090             'rowsinserted',
46091             
46092             
46093             'rowupdated',
46094             
46095             
46096             'refresh'
46097         );
46098         
46099         Ext.grid.GridView.superclass.constructor.call(this);
46100     },
46101
46102     
46103     
46104     
46105     masterTpl: new Ext.Template(
46106         '<div class="x-grid3" hidefocus="true">',
46107             '<div class="x-grid3-viewport">',
46108                 '<div class="x-grid3-header">',
46109                     '<div class="x-grid3-header-inner">',
46110                         '<div class="x-grid3-header-offset" style="{ostyle}">{header}</div>',
46111                     '</div>',
46112                     '<div class="x-clear"></div>',
46113                 '</div>',
46114                 '<div class="x-grid3-scroller">',
46115                     '<div class="x-grid3-body" style="{bstyle}">{body}</div>',
46116                     '<a href="#" class="x-grid3-focus" tabIndex="-1"></a>',
46117                 '</div>',
46118             '</div>',
46119             '<div class="x-grid3-resize-marker">&#160;</div>',
46120             '<div class="x-grid3-resize-proxy">&#160;</div>',
46121         '</div>'
46122     ),
46123     
46124     
46125     headerTpl: new Ext.Template(
46126         '<table border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
46127             '<thead>',
46128                 '<tr class="x-grid3-hd-row">{cells}</tr>',
46129             '</thead>',
46130         '</table>'
46131     ),
46132     
46133     
46134     bodyTpl: new Ext.Template('{rows}'),
46135     
46136     
46137     cellTpl: new Ext.Template(
46138         '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}" tabIndex="0" {cellAttr}>',
46139             '<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on" {attr}>{value}</div>',
46140         '</td>'
46141     ),
46142     
46143     
46144     initTemplates : function() {
46145         var templates = this.templates || {},
46146             template, name,
46147             
46148             headerCellTpl = new Ext.Template(
46149                 '<td class="x-grid3-hd x-grid3-cell x-grid3-td-{id} {css}" style="{style}">',
46150                     '<div {tooltip} {attr} class="x-grid3-hd-inner x-grid3-hd-{id}" unselectable="on" style="{istyle}">', 
46151                         this.grid.enableHdMenu ? '<a class="x-grid3-hd-btn" href="#"></a>' : '',
46152                         '{value}',
46153                         '<img alt="" class="x-grid3-sort-icon" src="', Ext.BLANK_IMAGE_URL, '" />',
46154                     '</div>',
46155                 '</td>'
46156             ),
46157         
46158             rowBodyText = [
46159                 '<tr class="x-grid3-row-body-tr" style="{bodyStyle}">',
46160                     '<td colspan="{cols}" class="x-grid3-body-cell" tabIndex="0" hidefocus="on">',
46161                         '<div class="x-grid3-row-body">{body}</div>',
46162                     '</td>',
46163                 '</tr>'
46164             ].join(""),
46165         
46166             innerText = [
46167                 '<table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
46168                      '<tbody>',
46169                         '<tr>{cells}</tr>',
46170                         this.enableRowBody ? rowBodyText : '',
46171                      '</tbody>',
46172                 '</table>'
46173             ].join("");
46174         
46175         Ext.applyIf(templates, {
46176             hcell   : headerCellTpl,
46177             cell    : this.cellTpl,
46178             body    : this.bodyTpl,
46179             header  : this.headerTpl,
46180             master  : this.masterTpl,
46181             row     : new Ext.Template('<div class="x-grid3-row {alt}" style="{tstyle}">' + innerText + '</div>'),
46182             rowInner: new Ext.Template(innerText)
46183         });
46184
46185         for (name in templates) {
46186             template = templates[name];
46187             
46188             if (template && Ext.isFunction(template.compile) && !template.compiled) {
46189                 template.disableFormats = true;
46190                 template.compile();
46191             }
46192         }
46193
46194         this.templates = templates;
46195         this.colRe = new RegExp('x-grid3-td-([^\\s]+)', '');
46196     },
46197
46198     
46199     fly : function(el) {
46200         if (!this._flyweight) {
46201             this._flyweight = new Ext.Element.Flyweight(document.body);
46202         }
46203         this._flyweight.dom = el;
46204         return this._flyweight;
46205     },
46206
46207     
46208     getEditorParent : function() {
46209         return this.scroller.dom;
46210     },
46211
46212     
46213     initElements : function() {
46214         var Element  = Ext.Element,
46215             el       = Ext.get(this.grid.getGridEl().dom.firstChild),
46216             mainWrap = new Element(el.child('div.x-grid3-viewport')),
46217             mainHd   = new Element(mainWrap.child('div.x-grid3-header')),
46218             scroller = new Element(mainWrap.child('div.x-grid3-scroller'));
46219         
46220         if (this.grid.hideHeaders) {
46221             mainHd.setDisplayed(false);
46222         }
46223         
46224         if (this.forceFit) {
46225             scroller.setStyle('overflow-x', 'hidden');
46226         }
46227         
46228         
46229         
46230         Ext.apply(this, {
46231             el      : el,
46232             mainWrap: mainWrap,
46233             scroller: scroller,
46234             mainHd  : mainHd,
46235             innerHd : mainHd.child('div.x-grid3-header-inner').dom,
46236             mainBody: new Element(Element.fly(scroller).child('div.x-grid3-body')),
46237             focusEl : new Element(Element.fly(scroller).child('a')),
46238             
46239             resizeMarker: new Element(el.child('div.x-grid3-resize-marker')),
46240             resizeProxy : new Element(el.child('div.x-grid3-resize-proxy'))
46241         });
46242         
46243         this.focusEl.swallowEvent('click', true);
46244     },
46245
46246     
46247     getRows : function() {
46248         return this.hasRows() ? this.mainBody.dom.childNodes : [];
46249     },
46250
46251     
46252
46253     
46254     findCell : function(el) {
46255         if (!el) {
46256             return false;
46257         }
46258         return this.fly(el).findParent(this.cellSelector, this.cellSelectorDepth);
46259     },
46260
46261     
46262     findCellIndex : function(el, requiredCls) {
46263         var cell = this.findCell(el),
46264             hasCls;
46265         
46266         if (cell) {
46267             hasCls = this.fly(cell).hasClass(requiredCls);
46268             if (!requiredCls || hasCls) {
46269                 return this.getCellIndex(cell);
46270             }
46271         }
46272         return false;
46273     },
46274
46275     
46276     getCellIndex : function(el) {
46277         if (el) {
46278             var match = el.className.match(this.colRe);
46279             
46280             if (match && match[1]) {
46281                 return this.cm.getIndexById(match[1]);
46282             }
46283         }
46284         return false;
46285     },
46286
46287     
46288     findHeaderCell : function(el) {
46289         var cell = this.findCell(el);
46290         return cell && this.fly(cell).hasClass(this.hdCls) ? cell : null;
46291     },
46292
46293     
46294     findHeaderIndex : function(el){
46295         return this.findCellIndex(el, this.hdCls);
46296     },
46297
46298     
46299     findRow : function(el) {
46300         if (!el) {
46301             return false;
46302         }
46303         return this.fly(el).findParent(this.rowSelector, this.rowSelectorDepth);
46304     },
46305
46306     
46307     findRowIndex : function(el) {
46308         var row = this.findRow(el);
46309         return row ? row.rowIndex : false;
46310     },
46311
46312     
46313     findRowBody : function(el) {
46314         if (!el) {
46315             return false;
46316         }
46317         
46318         return this.fly(el).findParent(this.rowBodySelector, this.rowBodySelectorDepth);
46319     },
46320
46321     
46322
46323     
46324     getRow : function(row) {
46325         return this.getRows()[row];
46326     },
46327
46328     
46329     getCell : function(row, col) {
46330         return Ext.fly(this.getRow(row)).query(this.cellSelector)[col]; 
46331     },
46332
46333     
46334     getHeaderCell : function(index) {
46335         return this.mainHd.dom.getElementsByTagName('td')[index];
46336     },
46337
46338     
46339
46340     
46341     addRowClass : function(rowId, cls) {
46342         var row = this.getRow(rowId);
46343         if (row) {
46344             this.fly(row).addClass(cls);
46345         }
46346     },
46347
46348     
46349     removeRowClass : function(row, cls) {
46350         var r = this.getRow(row);
46351         if(r){
46352             this.fly(r).removeClass(cls);
46353         }
46354     },
46355
46356     
46357     removeRow : function(row) {
46358         Ext.removeNode(this.getRow(row));
46359         this.syncFocusEl(row);
46360     },
46361
46362     
46363     removeRows : function(firstRow, lastRow) {
46364         var bd = this.mainBody.dom,
46365             rowIndex;
46366             
46367         for (rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
46368             Ext.removeNode(bd.childNodes[firstRow]);
46369         }
46370         
46371         this.syncFocusEl(firstRow);
46372     },
46373
46374     
46375     
46376     
46377     getScrollState : function() {
46378         var sb = this.scroller.dom;
46379         
46380         return {
46381             left: sb.scrollLeft, 
46382             top : sb.scrollTop
46383         };
46384     },
46385
46386     
46387     restoreScroll : function(state) {
46388         var sb = this.scroller.dom;
46389         sb.scrollLeft = state.left;
46390         sb.scrollTop  = state.top;
46391     },
46392
46393     
46394     scrollToTop : function() {
46395         var dom = this.scroller.dom;
46396         
46397         dom.scrollTop  = 0;
46398         dom.scrollLeft = 0;
46399     },
46400
46401     
46402     syncScroll : function() {
46403         this.syncHeaderScroll();
46404         var mb = this.scroller.dom;
46405         this.grid.fireEvent('bodyscroll', mb.scrollLeft, mb.scrollTop);
46406     },
46407
46408     
46409     syncHeaderScroll : function() {
46410         var innerHd    = this.innerHd,
46411             scrollLeft = this.scroller.dom.scrollLeft;
46412         
46413         innerHd.scrollLeft = scrollLeft;
46414         innerHd.scrollLeft = scrollLeft; 
46415     },
46416     
46417     
46418     updateSortIcon : function(col, dir) {
46419         var sortClasses = this.sortClasses,
46420             sortClass   = sortClasses[dir == "DESC" ? 1 : 0],
46421             headers     = this.mainHd.select('td').removeClass(sortClasses);
46422         
46423         headers.item(col).addClass(sortClass);
46424     },
46425
46426     
46427     updateAllColumnWidths : function() {
46428         var totalWidth = this.getTotalWidth(),
46429             colCount   = this.cm.getColumnCount(),
46430             rows       = this.getRows(),
46431             rowCount   = rows.length,
46432             widths     = [],
46433             row, rowFirstChild, trow, i, j;
46434         
46435         for (i = 0; i < colCount; i++) {
46436             widths[i] = this.getColumnWidth(i);
46437             this.getHeaderCell(i).style.width = widths[i];
46438         }
46439         
46440         this.updateHeaderWidth();
46441         
46442         for (i = 0; i < rowCount; i++) {
46443             row = rows[i];
46444             row.style.width = totalWidth;
46445             rowFirstChild = row.firstChild;
46446             
46447             if (rowFirstChild) {
46448                 rowFirstChild.style.width = totalWidth;
46449                 trow = rowFirstChild.rows[0];
46450                 
46451                 for (j = 0; j < colCount; j++) {
46452                     trow.childNodes[j].style.width = widths[j];
46453                 }
46454             }
46455         }
46456         
46457         this.onAllColumnWidthsUpdated(widths, totalWidth);
46458     },
46459
46460     
46461     updateColumnWidth : function(column, width) {
46462         var columnWidth = this.getColumnWidth(column),
46463             totalWidth  = this.getTotalWidth(),
46464             headerCell  = this.getHeaderCell(column),
46465             nodes       = this.getRows(),
46466             nodeCount   = nodes.length,
46467             row, i, firstChild;
46468         
46469         this.updateHeaderWidth();
46470         headerCell.style.width = columnWidth;
46471         
46472         for (i = 0; i < nodeCount; i++) {
46473             row = nodes[i];
46474             firstChild = row.firstChild;
46475             
46476             row.style.width = totalWidth;
46477             if (firstChild) {
46478                 firstChild.style.width = totalWidth;
46479                 firstChild.rows[0].childNodes[column].style.width = columnWidth;
46480             }
46481         }
46482         
46483         this.onColumnWidthUpdated(column, columnWidth, totalWidth);
46484     },
46485     
46486     
46487     updateColumnHidden : function(col, hidden) {
46488         var totalWidth = this.getTotalWidth(),
46489             display    = hidden ? 'none' : '',
46490             headerCell = this.getHeaderCell(col),
46491             nodes      = this.getRows(),
46492             nodeCount  = nodes.length,
46493             row, rowFirstChild, i;
46494         
46495         this.updateHeaderWidth();
46496         headerCell.style.display = display;
46497         
46498         for (i = 0; i < nodeCount; i++) {
46499             row = nodes[i];
46500             row.style.width = totalWidth;
46501             rowFirstChild = row.firstChild;
46502             
46503             if (rowFirstChild) {
46504                 rowFirstChild.style.width = totalWidth;
46505                 rowFirstChild.rows[0].childNodes[col].style.display = display;
46506             }
46507         }
46508         
46509         this.onColumnHiddenUpdated(col, hidden, totalWidth);
46510         delete this.lastViewWidth; 
46511         this.layout();
46512     },
46513
46514     
46515     doRender : function(columns, records, store, startRow, colCount, stripe) {
46516         var templates = this.templates,
46517             cellTemplate = templates.cell,
46518             rowTemplate = templates.row,
46519             last = colCount - 1,
46520             tstyle = 'width:' + this.getTotalWidth() + ';',
46521             
46522             rowBuffer = [],
46523             colBuffer = [],
46524             rowParams = {tstyle: tstyle},
46525             meta = {},
46526             len  = records.length,
46527             alt,
46528             column,
46529             record, i, j, rowIndex;
46530
46531         
46532         for (j = 0; j < len; j++) {
46533             record    = records[j];
46534             colBuffer = [];
46535
46536             rowIndex = j + startRow;
46537
46538             
46539             for (i = 0; i < colCount; i++) {
46540                 column = columns[i];
46541                 
46542                 meta.id    = column.id;
46543                 meta.css   = i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
46544                 meta.attr  = meta.cellAttr = '';
46545                 meta.style = column.style;
46546                 meta.value = column.renderer.call(column.scope, record.data[column.name], meta, record, rowIndex, i, store);
46547
46548                 if (Ext.isEmpty(meta.value)) {
46549                     meta.value = '&#160;';
46550                 }
46551
46552                 if (this.markDirty && record.dirty && typeof record.modified[column.name] != 'undefined') {
46553                     meta.css += ' x-grid3-dirty-cell';
46554                 }
46555
46556                 colBuffer[colBuffer.length] = cellTemplate.apply(meta);
46557             }
46558
46559             alt = [];
46560             
46561             if (stripe && ((rowIndex + 1) % 2 === 0)) {
46562                 alt[0] = 'x-grid3-row-alt';
46563             }
46564
46565             if (record.dirty) {
46566                 alt[1] = ' x-grid3-dirty-row';
46567             }
46568
46569             rowParams.cols = colCount;
46570
46571             if (this.getRowClass) {
46572                 alt[2] = this.getRowClass(record, rowIndex, rowParams, store);
46573             }
46574
46575             rowParams.alt   = alt.join(' ');
46576             rowParams.cells = colBuffer.join('');
46577
46578             rowBuffer[rowBuffer.length] = rowTemplate.apply(rowParams);
46579         }
46580
46581         return rowBuffer.join('');
46582     },
46583
46584     
46585     processRows : function(startRow, skipStripe) {
46586         if (!this.ds || this.ds.getCount() < 1) {
46587             return;
46588         }
46589
46590         var rows   = this.getRows(),
46591             length = rows.length,
46592             row, i;
46593
46594         skipStripe = skipStripe || !this.grid.stripeRows;
46595         startRow   = startRow   || 0;
46596
46597         for (i = 0; i < length; i++) {
46598             row = rows[i];
46599             if (row) {
46600                 row.rowIndex = i;
46601                 if (!skipStripe) {
46602                     row.className = row.className.replace(this.rowClsRe, ' ');
46603                     if ((i + 1) % 2 === 0){
46604                         row.className += ' x-grid3-row-alt';
46605                     }
46606                 }
46607             }
46608         }
46609
46610         
46611         if (startRow === 0) {
46612             Ext.fly(rows[0]).addClass(this.firstRowCls);
46613         }
46614
46615         Ext.fly(rows[length - 1]).addClass(this.lastRowCls);
46616     },
46617     
46618     
46619     afterRender : function() {
46620         if (!this.ds || !this.cm) {
46621             return;
46622         }
46623         
46624         this.mainBody.dom.innerHTML = this.renderBody() || '&#160;';
46625         this.processRows(0, true);
46626
46627         if (this.deferEmptyText !== true) {
46628             this.applyEmptyText();
46629         }
46630         
46631         this.grid.fireEvent('viewready', this.grid);
46632     },
46633     
46634     
46635     afterRenderUI: function() {
46636         var grid = this.grid;
46637         
46638         this.initElements();
46639
46640         
46641         Ext.fly(this.innerHd).on('click', this.handleHdDown, this);
46642
46643         this.mainHd.on({
46644             scope    : this,
46645             mouseover: this.handleHdOver,
46646             mouseout : this.handleHdOut,
46647             mousemove: this.handleHdMove
46648         });
46649
46650         this.scroller.on('scroll', this.syncScroll,  this);
46651         
46652         if (grid.enableColumnResize !== false) {
46653             this.splitZone = new Ext.grid.GridView.SplitDragZone(grid, this.mainHd.dom);
46654         }
46655
46656         if (grid.enableColumnMove) {
46657             this.columnDrag = new Ext.grid.GridView.ColumnDragZone(grid, this.innerHd);
46658             this.columnDrop = new Ext.grid.HeaderDropZone(grid, this.mainHd.dom);
46659         }
46660
46661         if (grid.enableHdMenu !== false) {
46662             this.hmenu = new Ext.menu.Menu({id: grid.id + '-hctx'});
46663             this.hmenu.add(
46664                 {itemId:'asc',  text: this.sortAscText,  cls: 'xg-hmenu-sort-asc'},
46665                 {itemId:'desc', text: this.sortDescText, cls: 'xg-hmenu-sort-desc'}
46666             );
46667
46668             if (grid.enableColumnHide !== false) {
46669                 this.colMenu = new Ext.menu.Menu({id:grid.id + '-hcols-menu'});
46670                 this.colMenu.on({
46671                     scope     : this,
46672                     beforeshow: this.beforeColMenuShow,
46673                     itemclick : this.handleHdMenuClick
46674                 });
46675                 this.hmenu.add('-', {
46676                     itemId:'columns',
46677                     hideOnClick: false,
46678                     text: this.columnsText,
46679                     menu: this.colMenu,
46680                     iconCls: 'x-cols-icon'
46681                 });
46682             }
46683
46684             this.hmenu.on('itemclick', this.handleHdMenuClick, this);
46685         }
46686
46687         if (grid.trackMouseOver) {
46688             this.mainBody.on({
46689                 scope    : this,
46690                 mouseover: this.onRowOver,
46691                 mouseout : this.onRowOut
46692             });
46693         }
46694
46695         if (grid.enableDragDrop || grid.enableDrag) {
46696             this.dragZone = new Ext.grid.GridDragZone(grid, {
46697                 ddGroup : grid.ddGroup || 'GridDD'
46698             });
46699         }
46700
46701         this.updateHeaderSortState();
46702     },
46703
46704     
46705     renderUI : function() {
46706         var templates = this.templates;
46707
46708         return templates.master.apply({
46709             body  : templates.body.apply({rows:'&#160;'}),
46710             header: this.renderHeaders(),
46711             ostyle: 'width:' + this.getOffsetWidth() + ';',
46712             bstyle: 'width:' + this.getTotalWidth()  + ';'
46713         });
46714     },
46715
46716     
46717     processEvent : function(name, e) {
46718         var target = e.getTarget(),
46719             grid   = this.grid,
46720             header = this.findHeaderIndex(target),
46721             row, cell, col, body;
46722
46723         grid.fireEvent(name, e);
46724
46725         if (header !== false) {
46726             grid.fireEvent('header' + name, grid, header, e);
46727         } else {
46728             row = this.findRowIndex(target);
46729
46730
46731
46732
46733             if (row !== false) {
46734                 cell = this.findCellIndex(target);
46735                 if (cell !== false) {
46736                     col = grid.colModel.getColumnAt(cell);
46737                     if (grid.fireEvent('cell' + name, grid, row, cell, e) !== false) {
46738                         if (!col || (col.processEvent && (col.processEvent(name, e, grid, row, cell) !== false))) {
46739                             grid.fireEvent('row' + name, grid, row, e);
46740                         }
46741                     }
46742                 } else {
46743                     if (grid.fireEvent('row' + name, grid, row, e) !== false) {
46744                         (body = this.findRowBody(target)) && grid.fireEvent('rowbody' + name, grid, row, e);
46745                     }
46746                 }
46747             } else {
46748                 grid.fireEvent('container' + name, grid, e);
46749             }
46750         }
46751     },
46752
46753     
46754     layout : function(initial) {
46755         if (!this.mainBody) {
46756             return; 
46757         }
46758
46759         var grid       = this.grid,
46760             gridEl     = grid.getGridEl(),
46761             gridSize   = gridEl.getSize(true),
46762             gridWidth  = gridSize.width,
46763             gridHeight = gridSize.height,
46764             scroller   = this.scroller,
46765             scrollStyle, headerHeight, scrollHeight;
46766         
46767         if (gridWidth < 20 || gridHeight < 20) {
46768             return;
46769         }
46770         
46771         if (grid.autoHeight) {
46772             scrollStyle = scroller.dom.style;
46773             scrollStyle.overflow = 'visible';
46774             
46775             if (Ext.isWebKit) {
46776                 scrollStyle.position = 'static';
46777             }
46778         } else {
46779             this.el.setSize(gridWidth, gridHeight);
46780             
46781             headerHeight = this.mainHd.getHeight();
46782             scrollHeight = gridHeight - headerHeight;
46783             
46784             scroller.setSize(gridWidth, scrollHeight);
46785             
46786             if (this.innerHd) {
46787                 this.innerHd.style.width = (gridWidth) + "px";
46788             }
46789         }
46790         
46791         if (this.forceFit || (initial === true && this.autoFill)) {
46792             if (this.lastViewWidth != gridWidth) {
46793                 this.fitColumns(false, false);
46794                 this.lastViewWidth = gridWidth;
46795             }
46796         } else {
46797             this.autoExpand();
46798             this.syncHeaderScroll();
46799         }
46800         
46801         this.onLayout(gridWidth, scrollHeight);
46802     },
46803
46804     
46805     
46806     onLayout : function(vw, vh) {
46807         
46808     },
46809
46810     onColumnWidthUpdated : function(col, w, tw) {
46811         
46812     },
46813
46814     onAllColumnWidthsUpdated : function(ws, tw) {
46815         
46816     },
46817
46818     onColumnHiddenUpdated : function(col, hidden, tw) {
46819         
46820     },
46821
46822     updateColumnText : function(col, text) {
46823         
46824     },
46825
46826     afterMove : function(colIndex) {
46827         
46828     },
46829
46830     
46831     
46832     init : function(grid) {
46833         this.grid = grid;
46834
46835         this.initTemplates();
46836         this.initData(grid.store, grid.colModel);
46837         this.initUI(grid);
46838     },
46839
46840     
46841     getColumnId : function(index){
46842         return this.cm.getColumnId(index);
46843     },
46844
46845     
46846     getOffsetWidth : function() {
46847         return (this.cm.getTotalWidth() + this.getScrollOffset()) + 'px';
46848     },
46849
46850     
46851     getScrollOffset: function() {
46852         return Ext.num(this.scrollOffset, Ext.getScrollBarWidth());
46853     },
46854
46855     
46856     renderHeaders : function() {
46857         var colModel   = this.cm,
46858             templates  = this.templates,
46859             headerTpl  = templates.hcell,
46860             properties = {},
46861             colCount   = colModel.getColumnCount(),
46862             last       = colCount - 1,
46863             cells      = [],
46864             i, cssCls;
46865         
46866         for (i = 0; i < colCount; i++) {
46867             if (i == 0) {
46868                 cssCls = 'x-grid3-cell-first ';
46869             } else {
46870                 cssCls = i == last ? 'x-grid3-cell-last ' : '';
46871             }
46872             
46873             properties = {
46874                 id     : colModel.getColumnId(i),
46875                 value  : colModel.getColumnHeader(i) || '',
46876                 style  : this.getColumnStyle(i, true),
46877                 css    : cssCls,
46878                 tooltip: this.getColumnTooltip(i)
46879             };
46880             
46881             if (colModel.config[i].align == 'right') {
46882                 properties.istyle = 'padding-right: 16px;';
46883             } else {
46884                 delete properties.istyle;
46885             }
46886             
46887             cells[i] = headerTpl.apply(properties);
46888         }
46889         
46890         return templates.header.apply({
46891             cells : cells.join(""),
46892             tstyle: String.format("width: {0};", this.getTotalWidth())
46893         });
46894     },
46895
46896     
46897     getColumnTooltip : function(i) {
46898         var tooltip = this.cm.getColumnTooltip(i);
46899         if (tooltip) {
46900             if (Ext.QuickTips.isEnabled()) {
46901                 return 'ext:qtip="' + tooltip + '"';
46902             } else {
46903                 return 'title="' + tooltip + '"';
46904             }
46905         }
46906         
46907         return '';
46908     },
46909
46910     
46911     beforeUpdate : function() {
46912         this.grid.stopEditing(true);
46913     },
46914
46915     
46916     updateHeaders : function() {
46917         this.innerHd.firstChild.innerHTML = this.renderHeaders();
46918         
46919         this.updateHeaderWidth(false);
46920     },
46921     
46922     
46923     updateHeaderWidth: function(updateMain) {
46924         var innerHdChild = this.innerHd.firstChild,
46925             totalWidth   = this.getTotalWidth();
46926         
46927         innerHdChild.style.width = this.getOffsetWidth();
46928         innerHdChild.firstChild.style.width = totalWidth;
46929         
46930         if (updateMain !== false) {
46931             this.mainBody.dom.style.width = totalWidth;
46932         }
46933     },
46934
46935     
46936     focusRow : function(row) {
46937         this.focusCell(row, 0, false);
46938     },
46939
46940     
46941     focusCell : function(row, col, hscroll) {
46942         this.syncFocusEl(this.ensureVisible(row, col, hscroll));
46943         
46944         var focusEl = this.focusEl;
46945         
46946         if (Ext.isGecko) {
46947             focusEl.focus();
46948         } else {
46949             focusEl.focus.defer(1, focusEl);
46950         }
46951     },
46952
46953     
46954     resolveCell : function(row, col, hscroll) {
46955         if (!Ext.isNumber(row)) {
46956             row = row.rowIndex;
46957         }
46958         
46959         if (!this.ds) {
46960             return null;
46961         }
46962         
46963         if (row < 0 || row >= this.ds.getCount()) {
46964             return null;
46965         }
46966         col = (col !== undefined ? col : 0);
46967
46968         var rowEl    = this.getRow(row),
46969             colModel = this.cm,
46970             colCount = colModel.getColumnCount(),
46971             cellEl;
46972             
46973         if (!(hscroll === false && col === 0)) {
46974             while (col < colCount && colModel.isHidden(col)) {
46975                 col++;
46976             }
46977             
46978             cellEl = this.getCell(row, col);
46979         }
46980
46981         return {row: rowEl, cell: cellEl};
46982     },
46983
46984     
46985     getResolvedXY : function(resolved) {
46986         if (!resolved) {
46987             return null;
46988         }
46989         
46990         var cell = resolved.cell,
46991             row  = resolved.row;
46992         
46993         if (cell) {
46994             return Ext.fly(cell).getXY();
46995         } else {
46996             return [this.el.getX(), Ext.fly(row).getY()];
46997         }
46998     },
46999
47000     
47001     syncFocusEl : function(row, col, hscroll) {
47002         var xy = row;
47003         
47004         if (!Ext.isArray(xy)) {
47005             row = Math.min(row, Math.max(0, this.getRows().length-1));
47006             
47007             if (isNaN(row)) {
47008                 return;
47009             }
47010             
47011             xy = this.getResolvedXY(this.resolveCell(row, col, hscroll));
47012         }
47013         
47014         this.focusEl.setXY(xy || this.scroller.getXY());
47015     },
47016
47017     
47018     ensureVisible : function(row, col, hscroll) {
47019         var resolved = this.resolveCell(row, col, hscroll);
47020         
47021         if (!resolved || !resolved.row) {
47022             return null;
47023         }
47024
47025         var rowEl  = resolved.row,
47026             cellEl = resolved.cell,
47027             c = this.scroller.dom,
47028             p = rowEl,
47029             ctop = 0,
47030             stop = this.el.dom;
47031
47032         while (p && p != stop) {
47033             ctop += p.offsetTop;
47034             p = p.offsetParent;
47035         }
47036
47037         ctop -= this.mainHd.dom.offsetHeight;
47038         stop = parseInt(c.scrollTop, 10);
47039
47040         var cbot = ctop + rowEl.offsetHeight,
47041             ch = c.clientHeight,
47042             sbot = stop + ch;
47043
47044
47045         if (ctop < stop) {
47046           c.scrollTop = ctop;
47047         } else if(cbot > sbot) {
47048             c.scrollTop = cbot-ch;
47049         }
47050
47051         if (hscroll !== false) {
47052             var cleft  = parseInt(cellEl.offsetLeft, 10),
47053                 cright = cleft + cellEl.offsetWidth,
47054                 sleft  = parseInt(c.scrollLeft, 10),
47055                 sright = sleft + c.clientWidth;
47056                 
47057             if (cleft < sleft) {
47058                 c.scrollLeft = cleft;
47059             } else if(cright > sright) {
47060                 c.scrollLeft = cright-c.clientWidth;
47061             }
47062         }
47063         
47064         return this.getResolvedXY(resolved);
47065     },
47066
47067     
47068     insertRows : function(dm, firstRow, lastRow, isUpdate) {
47069         var last = dm.getCount() - 1;
47070         if( !isUpdate && firstRow === 0 && lastRow >= last) {
47071             this.fireEvent('beforerowsinserted', this, firstRow, lastRow);
47072                 this.refresh();
47073             this.fireEvent('rowsinserted', this, firstRow, lastRow);
47074         } else {
47075             if (!isUpdate) {
47076                 this.fireEvent('beforerowsinserted', this, firstRow, lastRow);
47077             }
47078             var html = this.renderRows(firstRow, lastRow),
47079                 before = this.getRow(firstRow);
47080             if (before) {
47081                 if(firstRow === 0){
47082                     Ext.fly(this.getRow(0)).removeClass(this.firstRowCls);
47083                 }
47084                 Ext.DomHelper.insertHtml('beforeBegin', before, html);
47085             } else {
47086                 var r = this.getRow(last - 1);
47087                 if(r){
47088                     Ext.fly(r).removeClass(this.lastRowCls);
47089                 }
47090                 Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html);
47091             }
47092             if (!isUpdate) {
47093                 this.processRows(firstRow);
47094                 this.fireEvent('rowsinserted', this, firstRow, lastRow);
47095             } else if (firstRow === 0 || firstRow >= last) {
47096                 
47097                 Ext.fly(this.getRow(firstRow)).addClass(firstRow === 0 ? this.firstRowCls : this.lastRowCls);
47098             }
47099         }
47100         this.syncFocusEl(firstRow);
47101     },
47102
47103     
47104     deleteRows : function(dm, firstRow, lastRow) {
47105         if (dm.getRowCount() < 1) {
47106             this.refresh();
47107         } else {
47108             this.fireEvent('beforerowsdeleted', this, firstRow, lastRow);
47109
47110             this.removeRows(firstRow, lastRow);
47111
47112             this.processRows(firstRow);
47113             this.fireEvent('rowsdeleted', this, firstRow, lastRow);
47114         }
47115     },
47116
47117     
47118     getColumnStyle : function(colIndex, isHeader) {
47119         var colModel  = this.cm,
47120             colConfig = colModel.config,
47121             style     = isHeader ? '' : colConfig[colIndex].css || '',
47122             align     = colConfig[colIndex].align;
47123         
47124         style += String.format("width: {0};", this.getColumnWidth(colIndex));
47125         
47126         if (colModel.isHidden(colIndex)) {
47127             style += 'display: none; ';
47128         }
47129         
47130         if (align) {
47131             style += String.format("text-align: {0};", align);
47132         }
47133         
47134         return style;
47135     },
47136
47137     
47138     getColumnWidth : function(column) {
47139         var columnWidth = this.cm.getColumnWidth(column),
47140             borderWidth = this.borderWidth;
47141         
47142         if (Ext.isNumber(columnWidth)) {
47143             if (Ext.isBorderBox || (Ext.isWebKit && !Ext.isSafari2)) {
47144                 return columnWidth + "px";
47145             } else {
47146                 return Math.max(columnWidth - borderWidth, 0) + "px";
47147             }
47148         } else {
47149             return columnWidth;
47150         }
47151     },
47152
47153     
47154     getTotalWidth : function() {
47155         return this.cm.getTotalWidth() + 'px';
47156     },
47157
47158     
47159     fitColumns : function(preventRefresh, onlyExpand, omitColumn) {
47160         var grid          = this.grid,
47161             colModel      = this.cm,
47162             totalColWidth = colModel.getTotalWidth(false),
47163             gridWidth     = this.getGridInnerWidth(),
47164             extraWidth    = gridWidth - totalColWidth,
47165             columns       = [],
47166             extraCol      = 0,
47167             width         = 0,
47168             colWidth, fraction, i;
47169         
47170         
47171         if (gridWidth < 20 || extraWidth === 0) {
47172             return false;
47173         }
47174         
47175         var visibleColCount = colModel.getColumnCount(true),
47176             totalColCount   = colModel.getColumnCount(false),
47177             adjCount        = visibleColCount - (Ext.isNumber(omitColumn) ? 1 : 0);
47178         
47179         if (adjCount === 0) {
47180             adjCount = 1;
47181             omitColumn = undefined;
47182         }
47183         
47184         
47185         for (i = 0; i < totalColCount; i++) {
47186             if (!colModel.isFixed(i) && i !== omitColumn) {
47187                 colWidth = colModel.getColumnWidth(i);
47188                 columns.push(i, colWidth);
47189                 
47190                 if (!colModel.isHidden(i)) {
47191                     extraCol = i;
47192                     width += colWidth;
47193                 }
47194             }
47195         }
47196         
47197         fraction = (gridWidth - colModel.getTotalWidth()) / width;
47198         
47199         while (columns.length) {
47200             colWidth = columns.pop();
47201             i        = columns.pop();
47202             
47203             colModel.setColumnWidth(i, Math.max(grid.minColumnWidth, Math.floor(colWidth + colWidth * fraction)), true);
47204         }
47205         
47206         
47207         totalColWidth = colModel.getTotalWidth(false);
47208         
47209         if (totalColWidth > gridWidth) {
47210             var adjustCol = (adjCount == visibleColCount) ? extraCol : omitColumn,
47211                 newWidth  = Math.max(1, colModel.getColumnWidth(adjustCol) - (totalColWidth - gridWidth));
47212             
47213             colModel.setColumnWidth(adjustCol, newWidth, true);
47214         }
47215         
47216         if (preventRefresh !== true) {
47217             this.updateAllColumnWidths();
47218         }
47219         
47220         return true;
47221     },
47222
47223     
47224     autoExpand : function(preventUpdate) {
47225         var grid             = this.grid,
47226             colModel         = this.cm,
47227             gridWidth        = this.getGridInnerWidth(),
47228             totalColumnWidth = colModel.getTotalWidth(false),
47229             autoExpandColumn = grid.autoExpandColumn;
47230         
47231         if (!this.userResized && autoExpandColumn) {
47232             if (gridWidth != totalColumnWidth) {
47233                 
47234                 var colIndex     = colModel.getIndexById(autoExpandColumn),
47235                     currentWidth = colModel.getColumnWidth(colIndex),
47236                     desiredWidth = gridWidth - totalColumnWidth + currentWidth,
47237                     newWidth     = Math.min(Math.max(desiredWidth, grid.autoExpandMin), grid.autoExpandMax);
47238                 
47239                 if (currentWidth != newWidth) {
47240                     colModel.setColumnWidth(colIndex, newWidth, true);
47241                     
47242                     if (preventUpdate !== true) {
47243                         this.updateColumnWidth(colIndex, newWidth);
47244                     }
47245                 }
47246             }
47247         }
47248     },
47249     
47250     
47251     getGridInnerWidth: function() {
47252         return this.grid.getGridEl().getWidth(true) - this.getScrollOffset();
47253     },
47254
47255     
47256     getColumnData : function() {
47257         var columns  = [],
47258             colModel = this.cm,
47259             colCount = colModel.getColumnCount(),
47260             fields   = this.ds.fields,
47261             i, name;
47262         
47263         for (i = 0; i < colCount; i++) {
47264             name = colModel.getDataIndex(i);
47265             
47266             columns[i] = {
47267                 name    : Ext.isDefined(name) ? name : (fields.get(i) ? fields.get(i).name : undefined),
47268                 renderer: colModel.getRenderer(i),
47269                 scope   : colModel.getRendererScope(i),
47270                 id      : colModel.getColumnId(i),
47271                 style   : this.getColumnStyle(i)
47272             };
47273         }
47274         
47275         return columns;
47276     },
47277
47278     
47279     renderRows : function(startRow, endRow) {
47280         var grid     = this.grid,
47281             store    = grid.store,
47282             stripe   = grid.stripeRows,
47283             colModel = grid.colModel,
47284             colCount = colModel.getColumnCount(),
47285             rowCount = store.getCount(),
47286             records;
47287         
47288         if (rowCount < 1) {
47289             return '';
47290         }
47291         
47292         startRow = startRow || 0;
47293         endRow   = Ext.isDefined(endRow) ? endRow : rowCount - 1;
47294         records  = store.getRange(startRow, endRow);
47295         
47296         return this.doRender(this.getColumnData(), records, store, startRow, colCount, stripe);
47297     },
47298
47299     
47300     renderBody : function(){
47301         var markup = this.renderRows() || '&#160;';
47302         return this.templates.body.apply({rows: markup});
47303     },
47304
47305     
47306     refreshRow: function(record) {
47307         var store     = this.ds,
47308             colCount  = this.cm.getColumnCount(),
47309             columns   = this.getColumnData(),
47310             last      = colCount - 1,
47311             cls       = ['x-grid3-row'],
47312             rowParams = {
47313                 tstyle: String.format("width: {0};", this.getTotalWidth())
47314             },
47315             colBuffer = [],
47316             cellTpl   = this.templates.cell,
47317             rowIndex, row, column, meta, css, i;
47318         
47319         if (Ext.isNumber(record)) {
47320             rowIndex = record;
47321             record   = store.getAt(rowIndex);
47322         } else {
47323             rowIndex = store.indexOf(record);
47324         }
47325         
47326         
47327         if (!record || rowIndex < 0) {
47328             return;
47329         }
47330         
47331         
47332         for (i = 0; i < colCount; i++) {
47333             column = columns[i];
47334             
47335             if (i == 0) {
47336                 css = 'x-grid3-cell-first';
47337             } else {
47338                 css = (i == last) ? 'x-grid3-cell-last ' : '';
47339             }
47340             
47341             meta = {
47342                 id      : column.id,
47343                 style   : column.style,
47344                 css     : css,
47345                 attr    : "",
47346                 cellAttr: ""
47347             };
47348             
47349             meta.value = column.renderer.call(column.scope, record.data[column.name], meta, record, rowIndex, i, store);
47350             
47351             if (Ext.isEmpty(meta.value)) {
47352                 meta.value = '&#160;';
47353             }
47354             
47355             if (this.markDirty && record.dirty && typeof record.modified[column.name] != 'undefined') {
47356                 meta.css += ' x-grid3-dirty-cell';
47357             }
47358             
47359             colBuffer[i] = cellTpl.apply(meta);
47360         }
47361         
47362         row = this.getRow(rowIndex);
47363         row.className = '';
47364         
47365         if (this.grid.stripeRows && ((rowIndex + 1) % 2 === 0)) {
47366             cls.push('x-grid3-row-alt');
47367         }
47368         
47369         if (this.getRowClass) {
47370             rowParams.cols = colCount;
47371             cls.push(this.getRowClass(record, rowIndex, rowParams, store));
47372         }
47373         
47374         this.fly(row).addClass(cls).setStyle(rowParams.tstyle);
47375         rowParams.cells = colBuffer.join("");
47376         row.innerHTML = this.templates.rowInner.apply(rowParams);
47377         
47378         this.fireEvent('rowupdated', this, rowIndex, record);
47379     },
47380
47381     
47382     refresh : function(headersToo) {
47383         this.fireEvent('beforerefresh', this);
47384         this.grid.stopEditing(true);
47385
47386         var result = this.renderBody();
47387         this.mainBody.update(result).setWidth(this.getTotalWidth());
47388         if (headersToo === true) {
47389             this.updateHeaders();
47390             this.updateHeaderSortState();
47391         }
47392         this.processRows(0, true);
47393         this.layout();
47394         this.applyEmptyText();
47395         this.fireEvent('refresh', this);
47396     },
47397
47398     
47399     applyEmptyText : function() {
47400         if (this.emptyText && !this.hasRows()) {
47401             this.mainBody.update('<div class="x-grid-empty">' + this.emptyText + '</div>');
47402         }
47403     },
47404
47405     
47406     updateHeaderSortState : function() {
47407         var state = this.ds.getSortState();
47408         if (!state) {
47409             return;
47410         }
47411
47412         if (!this.sortState || (this.sortState.field != state.field || this.sortState.direction != state.direction)) {
47413             this.grid.fireEvent('sortchange', this.grid, state);
47414         }
47415
47416         this.sortState = state;
47417
47418         var sortColumn = this.cm.findColumnIndex(state.field);
47419         if (sortColumn != -1) {
47420             var sortDir = state.direction;
47421             this.updateSortIcon(sortColumn, sortDir);
47422         }
47423     },
47424
47425     
47426     clearHeaderSortState : function() {
47427         if (!this.sortState) {
47428             return;
47429         }
47430         this.grid.fireEvent('sortchange', this.grid, null);
47431         this.mainHd.select('td').removeClass(this.sortClasses);
47432         delete this.sortState;
47433     },
47434
47435     
47436     destroy : function() {
47437         var me              = this,
47438             grid            = me.grid,
47439             gridEl          = grid.getGridEl(),
47440             dragZone        = me.dragZone,
47441             splitZone       = me.splitZone,
47442             columnDrag      = me.columnDrag,
47443             columnDrop      = me.columnDrop,
47444             scrollToTopTask = me.scrollToTopTask,
47445             columnDragData,
47446             columnDragProxy;
47447         
47448         if (scrollToTopTask && scrollToTopTask.cancel) {
47449             scrollToTopTask.cancel();
47450         }
47451         
47452         Ext.destroyMembers(me, 'colMenu', 'hmenu');
47453
47454         me.initData(null, null);
47455         me.purgeListeners();
47456         
47457         Ext.fly(me.innerHd).un("click", me.handleHdDown, me);
47458
47459         if (grid.enableColumnMove) {
47460             columnDragData = columnDrag.dragData;
47461             columnDragProxy = columnDrag.proxy;
47462             Ext.destroy(
47463                 columnDrag.el,
47464                 columnDragProxy.ghost,
47465                 columnDragProxy.el,
47466                 columnDrop.el,
47467                 columnDrop.proxyTop,
47468                 columnDrop.proxyBottom,
47469                 columnDragData.ddel,
47470                 columnDragData.header
47471             );
47472             
47473             if (columnDragProxy.anim) {
47474                 Ext.destroy(columnDragProxy.anim);
47475             }
47476             
47477             delete columnDragProxy.ghost;
47478             delete columnDragData.ddel;
47479             delete columnDragData.header;
47480             columnDrag.destroy();
47481             
47482             delete Ext.dd.DDM.locationCache[columnDrag.id];
47483             delete columnDrag._domRef;
47484
47485             delete columnDrop.proxyTop;
47486             delete columnDrop.proxyBottom;
47487             columnDrop.destroy();
47488             delete Ext.dd.DDM.locationCache["gridHeader" + gridEl.id];
47489             delete columnDrop._domRef;
47490             delete Ext.dd.DDM.ids[columnDrop.ddGroup];
47491         }
47492
47493         if (splitZone) { 
47494             splitZone.destroy();
47495             delete splitZone._domRef;
47496             delete Ext.dd.DDM.ids["gridSplitters" + gridEl.id];
47497         }
47498
47499         Ext.fly(me.innerHd).removeAllListeners();
47500         Ext.removeNode(me.innerHd);
47501         delete me.innerHd;
47502
47503         Ext.destroy(
47504             me.el,
47505             me.mainWrap,
47506             me.mainHd,
47507             me.scroller,
47508             me.mainBody,
47509             me.focusEl,
47510             me.resizeMarker,
47511             me.resizeProxy,
47512             me.activeHdBtn,
47513             me._flyweight,
47514             dragZone,
47515             splitZone
47516         );
47517
47518         delete grid.container;
47519
47520         if (dragZone) {
47521             dragZone.destroy();
47522         }
47523
47524         Ext.dd.DDM.currentTarget = null;
47525         delete Ext.dd.DDM.locationCache[gridEl.id];
47526
47527         Ext.EventManager.removeResizeListener(me.onWindowResize, me);
47528     },
47529
47530     
47531     onDenyColumnHide : function() {
47532
47533     },
47534
47535     
47536     render : function() {
47537         if (this.autoFill) {
47538             var ct = this.grid.ownerCt;
47539             
47540             if (ct && ct.getLayout()) {
47541                 ct.on('afterlayout', function() {
47542                     this.fitColumns(true, true);
47543                     this.updateHeaders();
47544                     this.updateHeaderSortState();
47545                 }, this, {single: true});
47546             }
47547         } else if (this.forceFit) {
47548             this.fitColumns(true, false);
47549         } else if (this.grid.autoExpandColumn) {
47550             this.autoExpand(true);
47551         }
47552         
47553         this.grid.getGridEl().dom.innerHTML = this.renderUI();
47554         
47555         this.afterRenderUI();
47556     },
47557
47558     
47559     
47560     
47561     initData : function(newStore, newColModel) {
47562         var me = this;
47563         
47564         if (me.ds) {
47565             var oldStore = me.ds;
47566             
47567             oldStore.un('add', me.onAdd, me);
47568             oldStore.un('load', me.onLoad, me);
47569             oldStore.un('clear', me.onClear, me);
47570             oldStore.un('remove', me.onRemove, me);
47571             oldStore.un('update', me.onUpdate, me);
47572             oldStore.un('datachanged', me.onDataChange, me);
47573             
47574             if (oldStore !== newStore && oldStore.autoDestroy) {
47575                 oldStore.destroy();
47576             }
47577         }
47578         
47579         if (newStore) {
47580             newStore.on({
47581                 scope      : me,
47582                 load       : me.onLoad,
47583                 add        : me.onAdd,
47584                 remove     : me.onRemove,
47585                 update     : me.onUpdate,
47586                 clear      : me.onClear,
47587                 datachanged: me.onDataChange
47588             });
47589         }
47590         
47591         if (me.cm) {
47592             var oldColModel = me.cm;
47593             
47594             oldColModel.un('configchange', me.onColConfigChange, me);
47595             oldColModel.un('widthchange',  me.onColWidthChange, me);
47596             oldColModel.un('headerchange', me.onHeaderChange, me);
47597             oldColModel.un('hiddenchange', me.onHiddenChange, me);
47598             oldColModel.un('columnmoved',  me.onColumnMove, me);
47599         }
47600         
47601         if (newColModel) {
47602             delete me.lastViewWidth;
47603             
47604             newColModel.on({
47605                 scope       : me,
47606                 configchange: me.onColConfigChange,
47607                 widthchange : me.onColWidthChange,
47608                 headerchange: me.onHeaderChange,
47609                 hiddenchange: me.onHiddenChange,
47610                 columnmoved : me.onColumnMove
47611             });
47612         }
47613         
47614         me.ds = newStore;
47615         me.cm = newColModel;
47616     },
47617
47618     
47619     onDataChange : function(){
47620         this.refresh(true);
47621         this.updateHeaderSortState();
47622         this.syncFocusEl(0);
47623     },
47624
47625     
47626     onClear : function() {
47627         this.refresh();
47628         this.syncFocusEl(0);
47629     },
47630
47631     
47632     onUpdate : function(store, record) {
47633         this.refreshRow(record);
47634     },
47635
47636     
47637     onAdd : function(store, records, index) {
47638         this.insertRows(store, index, index + (records.length-1));
47639     },
47640
47641     
47642     onRemove : function(store, record, index, isUpdate) {
47643         if (isUpdate !== true) {
47644             this.fireEvent('beforerowremoved', this, index, record);
47645         }
47646         
47647         this.removeRow(index);
47648         
47649         if (isUpdate !== true) {
47650             this.processRows(index);
47651             this.applyEmptyText();
47652             this.fireEvent('rowremoved', this, index, record);
47653         }
47654     },
47655
47656     
47657     onLoad : function() {
47658         if (Ext.isGecko) {
47659             if (!this.scrollToTopTask) {
47660                 this.scrollToTopTask = new Ext.util.DelayedTask(this.scrollToTop, this);
47661             }
47662             this.scrollToTopTask.delay(1);
47663         } else {
47664             this.scrollToTop();
47665         }
47666     },
47667
47668     
47669     onColWidthChange : function(cm, col, width) {
47670         this.updateColumnWidth(col, width);
47671     },
47672
47673     
47674     onHeaderChange : function(cm, col, text) {
47675         this.updateHeaders();
47676     },
47677
47678     
47679     onHiddenChange : function(cm, col, hidden) {
47680         this.updateColumnHidden(col, hidden);
47681     },
47682
47683     
47684     onColumnMove : function(cm, oldIndex, newIndex) {
47685         this.indexMap = null;
47686         this.refresh(true);
47687         this.restoreScroll(this.getScrollState());
47688         
47689         this.afterMove(newIndex);
47690         this.grid.fireEvent('columnmove', oldIndex, newIndex);
47691     },
47692
47693     
47694     onColConfigChange : function() {
47695         delete this.lastViewWidth;
47696         this.indexMap = null;
47697         this.refresh(true);
47698     },
47699
47700     
47701     
47702     initUI : function(grid) {
47703         grid.on('headerclick', this.onHeaderClick, this);
47704     },
47705
47706     
47707     initEvents : Ext.emptyFn,
47708
47709     
47710     onHeaderClick : function(g, index) {
47711         if (this.headersDisabled || !this.cm.isSortable(index)) {
47712             return;
47713         }
47714         g.stopEditing(true);
47715         g.store.sort(this.cm.getDataIndex(index));
47716     },
47717
47718     
47719     onRowOver : function(e, target) {
47720         var row = this.findRowIndex(target);
47721         
47722         if (row !== false) {
47723             this.addRowClass(row, this.rowOverCls);
47724         }
47725     },
47726
47727     
47728     onRowOut : function(e, target) {
47729         var row = this.findRowIndex(target);
47730         
47731         if (row !== false && !e.within(this.getRow(row), true)) {
47732             this.removeRowClass(row, this.rowOverCls);
47733         }
47734     },
47735
47736     
47737     onRowSelect : function(row) {
47738         this.addRowClass(row, this.selectedRowClass);
47739     },
47740
47741     
47742     onRowDeselect : function(row) {
47743         this.removeRowClass(row, this.selectedRowClass);
47744     },
47745
47746     
47747     onCellSelect : function(row, col) {
47748         var cell = this.getCell(row, col);
47749         if (cell) {
47750             this.fly(cell).addClass('x-grid3-cell-selected');
47751         }
47752     },
47753
47754     
47755     onCellDeselect : function(row, col) {
47756         var cell = this.getCell(row, col);
47757         if (cell) {
47758             this.fly(cell).removeClass('x-grid3-cell-selected');
47759         }
47760     },
47761
47762     
47763     handleWheel : function(e) {
47764         e.stopPropagation();
47765     },
47766
47767     
47768     onColumnSplitterMoved : function(cellIndex, width) {
47769         this.userResized = true;
47770         this.grid.colModel.setColumnWidth(cellIndex, width, true);
47771
47772         if (this.forceFit) {
47773             this.fitColumns(true, false, cellIndex);
47774             this.updateAllColumnWidths();
47775         } else {
47776             this.updateColumnWidth(cellIndex, width);
47777             this.syncHeaderScroll();
47778         }
47779
47780         this.grid.fireEvent('columnresize', cellIndex, width);
47781     },
47782
47783     
47784     beforeColMenuShow : function() {
47785         var colModel = this.cm,
47786             colCount = colModel.getColumnCount(),
47787             colMenu  = this.colMenu,
47788             i;
47789
47790         colMenu.removeAll();
47791
47792         for (i = 0; i < colCount; i++) {
47793             if (colModel.config[i].hideable !== false) {
47794                 colMenu.add(new Ext.menu.CheckItem({
47795                     text       : colModel.getColumnHeader(i),
47796                     itemId     : 'col-' + colModel.getColumnId(i),
47797                     checked    : !colModel.isHidden(i),
47798                     disabled   : colModel.config[i].hideable === false,
47799                     hideOnClick: false
47800                 }));
47801             }
47802         }
47803     },
47804     
47805     
47806     handleHdMenuClick : function(item) {
47807         var store     = this.ds,
47808             dataIndex = this.cm.getDataIndex(this.hdCtxIndex);
47809
47810         switch (item.getItemId()) {
47811             case 'asc':
47812                 store.sort(dataIndex, 'ASC');
47813                 break;
47814             case 'desc':
47815                 store.sort(dataIndex, 'DESC');
47816                 break;
47817             default:
47818                 this.handleHdMenuClickDefault(item);
47819         }
47820         return true;
47821     },
47822     
47823     
47824     handleHdMenuClickDefault: function(item) {
47825         var colModel = this.cm,
47826             itemId   = item.getItemId(),
47827             index    = colModel.getIndexById(itemId.substr(4));
47828
47829         if (index != -1) {
47830             if (item.checked && colModel.getColumnsBy(this.isHideableColumn, this).length <= 1) {
47831                 this.onDenyColumnHide();
47832                 return;
47833             }
47834             colModel.setHidden(index, item.checked);
47835         }
47836     },
47837
47838     
47839     handleHdDown : function(e, target) {
47840         if (Ext.fly(target).hasClass('x-grid3-hd-btn')) {
47841             e.stopEvent();
47842             
47843             var colModel  = this.cm,
47844                 header    = this.findHeaderCell(target),
47845                 index     = this.getCellIndex(header),
47846                 sortable  = colModel.isSortable(index),
47847                 menu      = this.hmenu,
47848                 menuItems = menu.items,
47849                 menuCls   = this.headerMenuOpenCls;
47850             
47851             this.hdCtxIndex = index;
47852             
47853             Ext.fly(header).addClass(menuCls);
47854             menuItems.get('asc').setDisabled(!sortable);
47855             menuItems.get('desc').setDisabled(!sortable);
47856             
47857             menu.on('hide', function() {
47858                 Ext.fly(header).removeClass(menuCls);
47859             }, this, {single:true});
47860             
47861             menu.show(target, 'tl-bl?');
47862         }
47863     },
47864
47865     
47866     handleHdMove : function(e) {
47867         var header = this.findHeaderCell(this.activeHdRef);
47868         
47869         if (header && !this.headersDisabled) {
47870             var handleWidth  = this.splitHandleWidth || 5,
47871                 activeRegion = this.activeHdRegion,
47872                 headerStyle  = header.style,
47873                 colModel     = this.cm,
47874                 cursor       = '',
47875                 pageX        = e.getPageX();
47876                 
47877             if (this.grid.enableColumnResize !== false) {
47878                 var activeHeaderIndex = this.activeHdIndex,
47879                     previousVisible   = this.getPreviousVisible(activeHeaderIndex),
47880                     currentResizable  = colModel.isResizable(activeHeaderIndex),
47881                     previousResizable = previousVisible && colModel.isResizable(previousVisible),
47882                     inLeftResizer     = pageX - activeRegion.left <= handleWidth,
47883                     inRightResizer    = activeRegion.right - pageX <= (!this.activeHdBtn ? handleWidth : 2);
47884                 
47885                 if (inLeftResizer && previousResizable) {
47886                     cursor = Ext.isAir ? 'move' : Ext.isWebKit ? 'e-resize' : 'col-resize'; 
47887                 } else if (inRightResizer && currentResizable) {
47888                     cursor = Ext.isAir ? 'move' : Ext.isWebKit ? 'w-resize' : 'col-resize';
47889                 }
47890             }
47891             
47892             headerStyle.cursor = cursor;
47893         }
47894     },
47895     
47896     
47897     getPreviousVisible: function(index) {
47898         while (index > 0) {
47899             if (!this.cm.isHidden(index - 1)) {
47900                 return index;
47901             }
47902             index--;
47903         }
47904         return undefined;
47905     },
47906
47907     
47908     handleHdOver : function(e, target) {
47909         var header = this.findHeaderCell(target);
47910         
47911         if (header && !this.headersDisabled) {
47912             var fly = this.fly(header);
47913             
47914             this.activeHdRef = target;
47915             this.activeHdIndex = this.getCellIndex(header);
47916             this.activeHdRegion = fly.getRegion();
47917             
47918             if (!this.isMenuDisabled(this.activeHdIndex, fly)) {
47919                 fly.addClass('x-grid3-hd-over');
47920                 this.activeHdBtn = fly.child('.x-grid3-hd-btn');
47921                 
47922                 if (this.activeHdBtn) {
47923                     this.activeHdBtn.dom.style.height = (header.firstChild.offsetHeight - 1) + 'px';
47924                 }
47925             }
47926         }
47927     },
47928
47929     
47930     handleHdOut : function(e, target) {
47931         var header = this.findHeaderCell(target);
47932         
47933         if (header && (!Ext.isIE || !e.within(header, true))) {
47934             this.activeHdRef = null;
47935             this.fly(header).removeClass('x-grid3-hd-over');
47936             header.style.cursor = '';
47937         }
47938     },
47939     
47940     
47941     isMenuDisabled: function(cellIndex, el) {
47942         return this.cm.isMenuDisabled(cellIndex);
47943     },
47944
47945     
47946     hasRows : function() {
47947         var fc = this.mainBody.dom.firstChild;
47948         return fc && fc.nodeType == 1 && fc.className != 'x-grid-empty';
47949     },
47950     
47951     
47952     isHideableColumn : function(c) {
47953         return !c.hidden;
47954     },
47955
47956     
47957     bind : function(d, c) {
47958         this.initData(d, c);
47959     }
47960 });
47961
47962
47963
47964
47965 Ext.grid.GridView.SplitDragZone = Ext.extend(Ext.dd.DDProxy, {
47966
47967     constructor: function(grid, hd){
47968         this.grid = grid;
47969         this.view = grid.getView();
47970         this.marker = this.view.resizeMarker;
47971         this.proxy = this.view.resizeProxy;
47972         Ext.grid.GridView.SplitDragZone.superclass.constructor.call(this, hd,
47973             'gridSplitters' + this.grid.getGridEl().id, {
47974             dragElId : Ext.id(this.proxy.dom), resizeFrame:false
47975         });
47976         this.scroll = false;
47977         this.hw = this.view.splitHandleWidth || 5;
47978     },
47979
47980     b4StartDrag : function(x, y){
47981         this.dragHeadersDisabled = this.view.headersDisabled;
47982         this.view.headersDisabled = true;
47983         var h = this.view.mainWrap.getHeight();
47984         this.marker.setHeight(h);
47985         this.marker.show();
47986         this.marker.alignTo(this.view.getHeaderCell(this.cellIndex), 'tl-tl', [-2, 0]);
47987         this.proxy.setHeight(h);
47988         var w = this.cm.getColumnWidth(this.cellIndex),
47989             minw = Math.max(w-this.grid.minColumnWidth, 0);
47990         this.resetConstraints();
47991         this.setXConstraint(minw, 1000);
47992         this.setYConstraint(0, 0);
47993         this.minX = x - minw;
47994         this.maxX = x + 1000;
47995         this.startPos = x;
47996         Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
47997     },
47998
47999     allowHeaderDrag : function(e){
48000         return true;
48001     },
48002
48003     handleMouseDown : function(e){
48004         var t = this.view.findHeaderCell(e.getTarget());
48005         if(t && this.allowHeaderDrag(e)){
48006             var xy = this.view.fly(t).getXY(), 
48007                 x = xy[0],
48008                 exy = e.getXY(), 
48009                 ex = exy[0],
48010                 w = t.offsetWidth, 
48011                 adjust = false;
48012                 
48013             if((ex - x) <= this.hw){
48014                 adjust = -1;
48015             }else if((x+w) - ex <= this.hw){
48016                 adjust = 0;
48017             }
48018             if(adjust !== false){
48019                 this.cm = this.grid.colModel;
48020                 var ci = this.view.getCellIndex(t);
48021                 if(adjust == -1){
48022                   if (ci + adjust < 0) {
48023                     return;
48024                   }
48025                     while(this.cm.isHidden(ci+adjust)){
48026                         --adjust;
48027                         if(ci+adjust < 0){
48028                             return;
48029                         }
48030                     }
48031                 }
48032                 this.cellIndex = ci+adjust;
48033                 this.split = t.dom;
48034                 if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
48035                     Ext.grid.GridView.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
48036                 }
48037             }else if(this.view.columnDrag){
48038                 this.view.columnDrag.callHandleMouseDown(e);
48039             }
48040         }
48041     },
48042
48043     endDrag : function(e){
48044         this.marker.hide();
48045         var v = this.view,
48046             endX = Math.max(this.minX, e.getPageX()),
48047             diff = endX - this.startPos,
48048             disabled = this.dragHeadersDisabled;
48049             
48050         v.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);
48051         setTimeout(function(){
48052             v.headersDisabled = disabled;
48053         }, 50);
48054     },
48055
48056     autoOffset : function(){
48057         this.setDelta(0,0);
48058     }
48059 });
48060
48061 Ext.grid.PivotGridView = Ext.extend(Ext.grid.GridView, {
48062     
48063     
48064     colHeaderCellCls: 'grid-hd-group-cell',
48065     
48066     
48067     title: '',
48068     
48069     
48070     
48071     
48072     getColumnHeaders: function() {
48073         return this.grid.topAxis.buildHeaders();;
48074     },
48075     
48076     
48077     getRowHeaders: function() {
48078         return this.grid.leftAxis.buildHeaders();
48079     },
48080     
48081     
48082     renderRows : function(startRow, endRow) {
48083         var grid          = this.grid,
48084             rows          = grid.extractData(),
48085             rowCount      = rows.length,
48086             templates     = this.templates,
48087             renderer      = grid.renderer,
48088             hasRenderer   = typeof renderer == 'function',
48089             getCellCls    = this.getCellCls,
48090             hasGetCellCls = typeof getCellCls == 'function',
48091             cellTemplate  = templates.cell,
48092             rowTemplate   = templates.row,
48093             rowBuffer     = [],
48094             meta          = {},
48095             tstyle        = 'width:' + this.getGridInnerWidth() + 'px;',
48096             colBuffer, column, i;
48097         
48098         startRow = startRow || 0;
48099         endRow   = Ext.isDefined(endRow) ? endRow : rowCount - 1;
48100         
48101         for (i = 0; i < rowCount; i++) {
48102             row = rows[i];
48103             colCount  = row.length;
48104             colBuffer = [];
48105             
48106             rowIndex = startRow + i;
48107
48108             
48109             for (j = 0; j < colCount; j++) {
48110                 cell = row[j];
48111
48112                 meta.css   = j === 0 ? 'x-grid3-cell-first ' : (j == (colCount - 1) ? 'x-grid3-cell-last ' : '');
48113                 meta.attr  = meta.cellAttr = '';
48114                 meta.value = cell;
48115
48116                 if (Ext.isEmpty(meta.value)) {
48117                     meta.value = '&#160;';
48118                 }
48119                 
48120                 if (hasRenderer) {
48121                     meta.value = renderer(meta.value);
48122                 }
48123                 
48124                 if (hasGetCellCls) {
48125                     meta.css += getCellCls(meta.value) + ' ';
48126                 }
48127
48128                 colBuffer[colBuffer.length] = cellTemplate.apply(meta);
48129             }
48130             
48131             rowBuffer[rowBuffer.length] = rowTemplate.apply({
48132                 tstyle: tstyle,
48133                 cols  : colCount,
48134                 cells : colBuffer.join(""),
48135                 alt   : ''
48136             });
48137         }
48138         
48139         return rowBuffer.join("");
48140     },
48141     
48142     
48143     masterTpl: new Ext.Template(
48144         '<div class="x-grid3 x-pivotgrid" hidefocus="true">',
48145             '<div class="x-grid3-viewport">',
48146                 '<div class="x-grid3-header">',
48147                     '<div class="x-grid3-header-title"><span>{title}</span></div>',
48148                     '<div class="x-grid3-header-inner">',
48149                         '<div class="x-grid3-header-offset" style="{ostyle}"></div>',
48150                     '</div>',
48151                     '<div class="x-clear"></div>',
48152                 '</div>',
48153                 '<div class="x-grid3-scroller">',
48154                     '<div class="x-grid3-row-headers"></div>',
48155                     '<div class="x-grid3-body" style="{bstyle}">{body}</div>',
48156                     '<a href="#" class="x-grid3-focus" tabIndex="-1"></a>',
48157                 '</div>',
48158             '</div>',
48159             '<div class="x-grid3-resize-marker">&#160;</div>',
48160             '<div class="x-grid3-resize-proxy">&#160;</div>',
48161         '</div>'
48162     ),
48163     
48164     
48165     initTemplates: function() {
48166         Ext.grid.PivotGridView.superclass.initTemplates.apply(this, arguments);
48167         
48168         var templates = this.templates || {};
48169         if (!templates.gcell) {
48170             templates.gcell = new Ext.XTemplate(
48171                 '<td class="x-grid3-hd x-grid3-gcell x-grid3-td-{id} ux-grid-hd-group-row-{row} ' + this.colHeaderCellCls + '" style="{style}">',
48172                     '<div {tooltip} class="x-grid3-hd-inner x-grid3-hd-{id}" unselectable="on" style="{istyle}">', 
48173                         this.grid.enableHdMenu ? '<a class="x-grid3-hd-btn" href="#"></a>' : '', '{value}',
48174                     '</div>',
48175                 '</td>'
48176             );
48177         }
48178         
48179         this.templates = templates;
48180         this.hrowRe = new RegExp("ux-grid-hd-group-row-(\\d+)", "");
48181     },
48182     
48183     
48184     initElements: function() {
48185         Ext.grid.PivotGridView.superclass.initElements.apply(this, arguments);
48186         
48187         
48188         this.rowHeadersEl = new Ext.Element(this.scroller.child('div.x-grid3-row-headers'));
48189         
48190         
48191         this.headerTitleEl = new Ext.Element(this.mainHd.child('div.x-grid3-header-title'));
48192     },
48193     
48194     
48195     getGridInnerWidth: function() {
48196         var previousWidth = Ext.grid.PivotGridView.superclass.getGridInnerWidth.apply(this, arguments);
48197         
48198         return previousWidth - this.getTotalRowHeaderWidth();
48199     },
48200     
48201     
48202     getTotalRowHeaderWidth: function() {
48203         var headers = this.getRowHeaders(),
48204             length  = headers.length,
48205             total   = 0,
48206             i;
48207         
48208         for (i = 0; i< length; i++) {
48209             total += headers[i].width;
48210         }
48211         
48212         return total;
48213     },
48214     
48215     
48216     getTotalColumnHeaderHeight: function() {
48217         return this.getColumnHeaders().length * 21;
48218     },
48219     
48220     
48221     renderUI : function() {
48222         var templates  = this.templates,
48223             innerWidth = this.getGridInnerWidth();
48224             
48225         return templates.master.apply({
48226             body  : templates.body.apply({rows:'&#160;'}),
48227             ostyle: 'width:' + innerWidth + 'px',
48228             bstyle: 'width:' + innerWidth + 'px'
48229         });
48230     },
48231     
48232     
48233     onLayout: function(width, height) {
48234         Ext.grid.PivotGridView.superclass.onLayout.apply(this, arguments);
48235         
48236         var width = this.getGridInnerWidth();
48237         
48238         this.resizeColumnHeaders(width);
48239         this.resizeAllRows(width);
48240     },
48241     
48242     
48243     refresh : function(headersToo) {
48244         this.fireEvent('beforerefresh', this);
48245         this.grid.stopEditing(true);
48246         
48247         var result = this.renderBody();
48248         this.mainBody.update(result).setWidth(this.getGridInnerWidth());
48249         if (headersToo === true) {
48250             this.updateHeaders();
48251             this.updateHeaderSortState();
48252         }
48253         this.processRows(0, true);
48254         this.layout();
48255         this.applyEmptyText();
48256         this.fireEvent('refresh', this);
48257     },
48258     
48259     
48260     renderHeaders: Ext.emptyFn,
48261     
48262     
48263     fitColumns: Ext.emptyFn,
48264     
48265     
48266     resizeColumnHeaders: function(width) {
48267         var topAxis = this.grid.topAxis;
48268         
48269         if (topAxis.rendered) {
48270             topAxis.el.setWidth(width);
48271         }
48272     },
48273     
48274     
48275     resizeRowHeaders: function() {
48276         var rowHeaderWidth = this.getTotalRowHeaderWidth(),
48277             marginStyle    = String.format("margin-left: {0}px;", rowHeaderWidth);
48278         
48279         this.rowHeadersEl.setWidth(rowHeaderWidth);
48280         this.mainBody.applyStyles(marginStyle);
48281         Ext.fly(this.innerHd).applyStyles(marginStyle);
48282         
48283         this.headerTitleEl.setWidth(rowHeaderWidth);
48284         this.headerTitleEl.setHeight(this.getTotalColumnHeaderHeight());
48285     },
48286     
48287     
48288     resizeAllRows: function(width) {
48289         var rows   = this.getRows(),
48290             length = rows.length,
48291             i;
48292         
48293         for (i = 0; i < length; i++) {
48294             Ext.fly(rows[i]).setWidth(width);
48295             Ext.fly(rows[i]).child('table').setWidth(width);
48296         }
48297     },
48298     
48299     
48300     updateHeaders: function() {
48301         this.renderGroupRowHeaders();
48302         this.renderGroupColumnHeaders();
48303     },
48304     
48305     
48306     renderGroupRowHeaders: function() {
48307         var leftAxis = this.grid.leftAxis;
48308         
48309         this.resizeRowHeaders();
48310         leftAxis.rendered = false;
48311         leftAxis.render(this.rowHeadersEl);
48312         
48313         this.setTitle(this.title);
48314     },
48315     
48316     
48317     setTitle: function(title) {
48318         this.headerTitleEl.child('span').dom.innerHTML = title;
48319     },
48320     
48321     
48322     renderGroupColumnHeaders: function() {
48323         var topAxis = this.grid.topAxis;
48324         
48325         topAxis.rendered = false;
48326         topAxis.render(this.innerHd.firstChild);
48327     },
48328     
48329     
48330     isMenuDisabled: function(cellIndex, el) {
48331         return true;
48332     }
48333 });
48334 Ext.grid.PivotAxis = Ext.extend(Ext.Component, {
48335     
48336     orientation: 'horizontal',
48337     
48338     
48339     defaultHeaderWidth: 80,
48340     
48341     
48342     paddingWidth: 7,
48343     
48344     
48345     setDimensions: function(dimensions) {
48346         this.dimensions = dimensions;
48347     },
48348     
48349     
48350     onRender: function(ct, position) {
48351         var rows = this.orientation == 'horizontal'
48352                  ? this.renderHorizontalRows()
48353                  : this.renderVerticalRows();
48354         
48355         this.el = Ext.DomHelper.overwrite(ct.dom, {tag: 'table', cn: rows}, true);
48356     },
48357     
48358     
48359     renderHorizontalRows: function() {
48360         var headers  = this.buildHeaders(),
48361             rowCount = headers.length,
48362             rows     = [],
48363             cells, cols, colCount, i, j;
48364         
48365         for (i = 0; i < rowCount; i++) {
48366             cells = [];
48367             cols  = headers[i].items;
48368             colCount = cols.length;
48369
48370             for (j = 0; j < colCount; j++) {
48371                 cells.push({
48372                     tag: 'td',
48373                     html: cols[j].header,
48374                     colspan: cols[j].span
48375                 });
48376             }
48377
48378             rows[i] = {
48379                 tag: 'tr',
48380                 cn: cells
48381             };
48382         }
48383         
48384         return rows;
48385     },
48386     
48387     
48388     renderVerticalRows: function() {
48389         var headers  = this.buildHeaders(),
48390             colCount = headers.length,
48391             rowCells = [],
48392             rows     = [],
48393             rowCount, col, row, colWidth, i, j;
48394         
48395         for (i = 0; i < colCount; i++) {
48396             col = headers[i];
48397             colWidth = col.width || 80;
48398             rowCount = col.items.length;
48399             
48400             for (j = 0; j < rowCount; j++) {
48401                 row = col.items[j];
48402                 
48403                 rowCells[row.start] = rowCells[row.start] || [];
48404                 rowCells[row.start].push({
48405                     tag    : 'td',
48406                     html   : row.header,
48407                     rowspan: row.span,
48408                     width  : Ext.isBorderBox ? colWidth : colWidth - this.paddingWidth
48409                 });
48410             }
48411         }
48412         
48413         rowCount = rowCells.length;
48414         for (i = 0; i < rowCount; i++) {
48415             rows[i] = {
48416                 tag: 'tr',
48417                 cn : rowCells[i]
48418             };
48419         }
48420         
48421         return rows;
48422     },
48423     
48424     
48425     getTuples: function() {
48426         var newStore = new Ext.data.Store({});
48427         
48428         newStore.data = this.store.data.clone();
48429         newStore.fields = this.store.fields;
48430         
48431         var sorters    = [],
48432             dimensions = this.dimensions,
48433             length     = dimensions.length,
48434             i;
48435         
48436         for (i = 0; i < length; i++) {
48437             sorters.push({
48438                 field    : dimensions[i].dataIndex,
48439                 direction: dimensions[i].direction || 'ASC'
48440             });
48441         }
48442         
48443         newStore.sort(sorters);
48444         
48445         var records = newStore.data.items,
48446             hashes  = [],
48447             tuples  = [],
48448             recData, hash, info, data, key;
48449         
48450         length = records.length;
48451         
48452         for (i = 0; i < length; i++) {
48453             info = this.getRecordInfo(records[i]);
48454             data = info.data;
48455             hash = "";
48456             
48457             for (key in data) {
48458                 hash += data[key] + '---';
48459             }
48460             
48461             if (hashes.indexOf(hash) == -1) {
48462                 hashes.push(hash);
48463                 tuples.push(info);
48464             }
48465         }
48466         
48467         newStore.destroy();
48468         
48469         return tuples;
48470     },
48471     
48472     
48473     getRecordInfo: function(record) {
48474         var dimensions = this.dimensions,
48475             length  = dimensions.length,
48476             data    = {},
48477             dimension, dataIndex, i;
48478         
48479         
48480         for (i = 0; i < length; i++) {
48481             dimension = dimensions[i];
48482             dataIndex = dimension.dataIndex;
48483             
48484             data[dataIndex] = record.get(dataIndex);
48485         }
48486         
48487         
48488         
48489         var createMatcherFunction = function(data) {
48490             return function(record) {
48491                 for (var dataIndex in data) {
48492                     if (record.get(dataIndex) != data[dataIndex]) {
48493                         return false;
48494                     }
48495                 }
48496                 
48497                 return true;
48498             };
48499         };
48500         
48501         return {
48502             data: data,
48503             matcher: createMatcherFunction(data)
48504         };
48505     },
48506     
48507     
48508     buildHeaders: function() {
48509         var tuples     = this.getTuples(),
48510             rowCount   = tuples.length,
48511             dimensions = this.dimensions,
48512             colCount   = dimensions.length,
48513             headers    = [],
48514             tuple, rows, currentHeader, previousHeader, span, start, isLast, changed, i, j;
48515         
48516         for (i = 0; i < colCount; i++) {
48517             dimension = dimensions[i];
48518             rows  = [];
48519             span  = 0;
48520             start = 0;
48521             
48522             for (j = 0; j < rowCount; j++) {
48523                 tuple  = tuples[j];
48524                 isLast = j == (rowCount - 1);
48525                 currentHeader = tuple.data[dimension.dataIndex];
48526                 
48527                 
48528                 changed = previousHeader != undefined && previousHeader != currentHeader;
48529                 if (i > 0 && j > 0) {
48530                     changed = changed || tuple.data[dimensions[i-1].dataIndex] != tuples[j-1].data[dimensions[i-1].dataIndex];
48531                 }
48532                 
48533                 if (changed) {                    
48534                     rows.push({
48535                         header: previousHeader,
48536                         span  : span,
48537                         start : start
48538                     });
48539                     
48540                     start += span;
48541                     span = 0;
48542                 }
48543                 
48544                 if (isLast) {
48545                     rows.push({
48546                         header: currentHeader,
48547                         span  : span + 1,
48548                         start : start
48549                     });
48550                     
48551                     start += span;
48552                     span = 0;
48553                 }
48554                 
48555                 previousHeader = currentHeader;
48556                 span++;
48557             }
48558             
48559             headers.push({
48560                 items: rows,
48561                 width: dimension.width || this.defaultHeaderWidth
48562             });
48563             
48564             previousHeader = undefined;
48565         }
48566         
48567         return headers;
48568     }
48569 });
48570
48571
48572 Ext.grid.HeaderDragZone = Ext.extend(Ext.dd.DragZone, {
48573     maxDragWidth: 120,
48574     
48575     constructor : function(grid, hd, hd2){
48576         this.grid = grid;
48577         this.view = grid.getView();
48578         this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
48579         Ext.grid.HeaderDragZone.superclass.constructor.call(this, hd);
48580         if(hd2){
48581             this.setHandleElId(Ext.id(hd));
48582             this.setOuterHandleElId(Ext.id(hd2));
48583         }
48584         this.scroll = false;
48585     },
48586     
48587     getDragData : function(e){
48588         var t = Ext.lib.Event.getTarget(e),
48589             h = this.view.findHeaderCell(t);
48590         if(h){
48591             return {ddel: h.firstChild, header:h};
48592         }
48593         return false;
48594     },
48595
48596     onInitDrag : function(e){
48597         
48598         this.dragHeadersDisabled = this.view.headersDisabled;
48599         this.view.headersDisabled = true;
48600         var clone = this.dragData.ddel.cloneNode(true);
48601         clone.id = Ext.id();
48602         clone.style.width = Math.min(this.dragData.header.offsetWidth,this.maxDragWidth) + "px";
48603         this.proxy.update(clone);
48604         return true;
48605     },
48606
48607     afterValidDrop : function(){
48608         this.completeDrop();
48609     },
48610
48611     afterInvalidDrop : function(){
48612         this.completeDrop();
48613     },
48614     
48615     completeDrop: function(){
48616         var v = this.view,
48617             disabled = this.dragHeadersDisabled;
48618         setTimeout(function(){
48619             v.headersDisabled = disabled;
48620         }, 50);
48621     }
48622 });
48623
48624
48625
48626 Ext.grid.HeaderDropZone = Ext.extend(Ext.dd.DropZone, {
48627     proxyOffsets : [-4, -9],
48628     fly: Ext.Element.fly,
48629     
48630     constructor : function(grid, hd, hd2){
48631         this.grid = grid;
48632         this.view = grid.getView();
48633         
48634         this.proxyTop = Ext.DomHelper.append(document.body, {
48635             cls:"col-move-top", html:"&#160;"
48636         }, true);
48637         this.proxyBottom = Ext.DomHelper.append(document.body, {
48638             cls:"col-move-bottom", html:"&#160;"
48639         }, true);
48640         this.proxyTop.hide = this.proxyBottom.hide = function(){
48641             this.setLeftTop(-100,-100);
48642             this.setStyle("visibility", "hidden");
48643         };
48644         this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
48645         
48646         
48647         Ext.grid.HeaderDropZone.superclass.constructor.call(this, grid.getGridEl().dom);
48648     },
48649
48650     getTargetFromEvent : function(e){
48651         var t = Ext.lib.Event.getTarget(e),
48652             cindex = this.view.findCellIndex(t);
48653         if(cindex !== false){
48654             return this.view.getHeaderCell(cindex);
48655         }
48656     },
48657
48658     nextVisible : function(h){
48659         var v = this.view, cm = this.grid.colModel;
48660         h = h.nextSibling;
48661         while(h){
48662             if(!cm.isHidden(v.getCellIndex(h))){
48663                 return h;
48664             }
48665             h = h.nextSibling;
48666         }
48667         return null;
48668     },
48669
48670     prevVisible : function(h){
48671         var v = this.view, cm = this.grid.colModel;
48672         h = h.prevSibling;
48673         while(h){
48674             if(!cm.isHidden(v.getCellIndex(h))){
48675                 return h;
48676             }
48677             h = h.prevSibling;
48678         }
48679         return null;
48680     },
48681
48682     positionIndicator : function(h, n, e){
48683         var x = Ext.lib.Event.getPageX(e),
48684             r = Ext.lib.Dom.getRegion(n.firstChild),
48685             px, 
48686             pt, 
48687             py = r.top + this.proxyOffsets[1];
48688         if((r.right - x) <= (r.right-r.left)/2){
48689             px = r.right+this.view.borderWidth;
48690             pt = "after";
48691         }else{
48692             px = r.left;
48693             pt = "before";
48694         }
48695
48696         if(this.grid.colModel.isFixed(this.view.getCellIndex(n))){
48697             return false;
48698         }
48699
48700         px +=  this.proxyOffsets[0];
48701         this.proxyTop.setLeftTop(px, py);
48702         this.proxyTop.show();
48703         if(!this.bottomOffset){
48704             this.bottomOffset = this.view.mainHd.getHeight();
48705         }
48706         this.proxyBottom.setLeftTop(px, py+this.proxyTop.dom.offsetHeight+this.bottomOffset);
48707         this.proxyBottom.show();
48708         return pt;
48709     },
48710
48711     onNodeEnter : function(n, dd, e, data){
48712         if(data.header != n){
48713             this.positionIndicator(data.header, n, e);
48714         }
48715     },
48716
48717     onNodeOver : function(n, dd, e, data){
48718         var result = false;
48719         if(data.header != n){
48720             result = this.positionIndicator(data.header, n, e);
48721         }
48722         if(!result){
48723             this.proxyTop.hide();
48724             this.proxyBottom.hide();
48725         }
48726         return result ? this.dropAllowed : this.dropNotAllowed;
48727     },
48728
48729     onNodeOut : function(n, dd, e, data){
48730         this.proxyTop.hide();
48731         this.proxyBottom.hide();
48732     },
48733
48734     onNodeDrop : function(n, dd, e, data){
48735         var h = data.header;
48736         if(h != n){
48737             var cm = this.grid.colModel,
48738                 x = Ext.lib.Event.getPageX(e),
48739                 r = Ext.lib.Dom.getRegion(n.firstChild),
48740                 pt = (r.right - x) <= ((r.right-r.left)/2) ? "after" : "before",
48741                 oldIndex = this.view.getCellIndex(h),
48742                 newIndex = this.view.getCellIndex(n);
48743             if(pt == "after"){
48744                 newIndex++;
48745             }
48746             if(oldIndex < newIndex){
48747                 newIndex--;
48748             }
48749             cm.moveColumn(oldIndex, newIndex);
48750             return true;
48751         }
48752         return false;
48753     }
48754 });
48755
48756 Ext.grid.GridView.ColumnDragZone = Ext.extend(Ext.grid.HeaderDragZone, {
48757     
48758     constructor : function(grid, hd){
48759         Ext.grid.GridView.ColumnDragZone.superclass.constructor.call(this, grid, hd, null);
48760         this.proxy.el.addClass('x-grid3-col-dd');
48761     },
48762     
48763     handleMouseDown : function(e){
48764     },
48765
48766     callHandleMouseDown : function(e){
48767         Ext.grid.GridView.ColumnDragZone.superclass.handleMouseDown.call(this, e);
48768     }
48769 });
48770
48771 Ext.grid.SplitDragZone = Ext.extend(Ext.dd.DDProxy, {
48772     fly: Ext.Element.fly,
48773     
48774     constructor : function(grid, hd, hd2){
48775         this.grid = grid;
48776         this.view = grid.getView();
48777         this.proxy = this.view.resizeProxy;
48778         Ext.grid.SplitDragZone.superclass.constructor.call(this, hd,
48779             "gridSplitters" + this.grid.getGridEl().id, {
48780             dragElId : Ext.id(this.proxy.dom), resizeFrame:false
48781         });
48782         this.setHandleElId(Ext.id(hd));
48783         this.setOuterHandleElId(Ext.id(hd2));
48784         this.scroll = false;
48785     },
48786
48787     b4StartDrag : function(x, y){
48788         this.view.headersDisabled = true;
48789         this.proxy.setHeight(this.view.mainWrap.getHeight());
48790         var w = this.cm.getColumnWidth(this.cellIndex);
48791         var minw = Math.max(w-this.grid.minColumnWidth, 0);
48792         this.resetConstraints();
48793         this.setXConstraint(minw, 1000);
48794         this.setYConstraint(0, 0);
48795         this.minX = x - minw;
48796         this.maxX = x + 1000;
48797         this.startPos = x;
48798         Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
48799     },
48800
48801
48802     handleMouseDown : function(e){
48803         var ev = Ext.EventObject.setEvent(e);
48804         var t = this.fly(ev.getTarget());
48805         if(t.hasClass("x-grid-split")){
48806             this.cellIndex = this.view.getCellIndex(t.dom);
48807             this.split = t.dom;
48808             this.cm = this.grid.colModel;
48809             if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
48810                 Ext.grid.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
48811             }
48812         }
48813     },
48814
48815     endDrag : function(e){
48816         this.view.headersDisabled = false;
48817         var endX = Math.max(this.minX, Ext.lib.Event.getPageX(e));
48818         var diff = endX - this.startPos;
48819         this.view.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);
48820     },
48821
48822     autoOffset : function(){
48823         this.setDelta(0,0);
48824     }
48825 });
48826 Ext.grid.GridDragZone = function(grid, config){
48827     this.view = grid.getView();
48828     Ext.grid.GridDragZone.superclass.constructor.call(this, this.view.mainBody.dom, config);
48829     this.scroll = false;
48830     this.grid = grid;
48831     this.ddel = document.createElement('div');
48832     this.ddel.className = 'x-grid-dd-wrap';
48833 };
48834
48835 Ext.extend(Ext.grid.GridDragZone, Ext.dd.DragZone, {
48836     ddGroup : "GridDD",
48837
48838     
48839     getDragData : function(e){
48840         var t = Ext.lib.Event.getTarget(e);
48841         var rowIndex = this.view.findRowIndex(t);
48842         if(rowIndex !== false){
48843             var sm = this.grid.selModel;
48844             if(!sm.isSelected(rowIndex) || e.hasModifier()){
48845                 sm.handleMouseDown(this.grid, rowIndex, e);
48846             }
48847             return {grid: this.grid, ddel: this.ddel, rowIndex: rowIndex, selections:sm.getSelections()};
48848         }
48849         return false;
48850     },
48851
48852     
48853     onInitDrag : function(e){
48854         var data = this.dragData;
48855         this.ddel.innerHTML = this.grid.getDragDropText();
48856         this.proxy.update(this.ddel);
48857         
48858     },
48859
48860     
48861     afterRepair : function(){
48862         this.dragging = false;
48863     },
48864
48865     
48866     getRepairXY : function(e, data){
48867         return false;
48868     },
48869
48870     onEndDrag : function(data, e){
48871         
48872     },
48873
48874     onValidDrop : function(dd, e, id){
48875         
48876         this.hideProxy();
48877     },
48878
48879     beforeInvalidDrop : function(e, id){
48880
48881     }
48882 });
48883
48884 Ext.grid.ColumnModel = Ext.extend(Ext.util.Observable, {
48885     
48886     defaultWidth: 100,
48887
48888     
48889     defaultSortable: false,
48890
48891     
48892
48893     
48894
48895     constructor : function(config) {
48896         
48897             if (config.columns) {
48898                 Ext.apply(this, config);
48899                 this.setConfig(config.columns, true);
48900             } else {
48901                 this.setConfig(config, true);
48902             }
48903             
48904             this.addEvents(
48905                 
48906                 "widthchange",
48907                 
48908                 
48909                 "headerchange",
48910                 
48911                 
48912                 "hiddenchange",
48913                 
48914                 
48915                 "columnmoved",
48916                 
48917                 
48918                 "configchange"
48919             );
48920             
48921             Ext.grid.ColumnModel.superclass.constructor.call(this);
48922     },
48923
48924     
48925     getColumnId : function(index) {
48926         return this.config[index].id;
48927     },
48928
48929     getColumnAt : function(index) {
48930         return this.config[index];
48931     },
48932
48933     
48934     setConfig : function(config, initial) {
48935         var i, c, len;
48936         
48937         if (!initial) { 
48938             delete this.totalWidth;
48939             
48940             for (i = 0, len = this.config.length; i < len; i++) {
48941                 c = this.config[i];
48942                 
48943                 if (c.setEditor) {
48944                     
48945                     c.setEditor(null);
48946                 }
48947             }
48948         }
48949
48950         
48951         this.defaults = Ext.apply({
48952             width: this.defaultWidth,
48953             sortable: this.defaultSortable
48954         }, this.defaults);
48955
48956         this.config = config;
48957         this.lookup = {};
48958
48959         for (i = 0, len = config.length; i < len; i++) {
48960             c = Ext.applyIf(config[i], this.defaults);
48961             
48962             
48963             if (Ext.isEmpty(c.id)) {
48964                 c.id = i;
48965             }
48966             
48967             if (!c.isColumn) {
48968                 var Cls = Ext.grid.Column.types[c.xtype || 'gridcolumn'];
48969                 c = new Cls(c);
48970                 config[i] = c;
48971             }
48972             
48973             this.lookup[c.id] = c;
48974         }
48975         
48976         if (!initial) {
48977             this.fireEvent('configchange', this);
48978         }
48979     },
48980
48981     
48982     getColumnById : function(id) {
48983         return this.lookup[id];
48984     },
48985
48986     
48987     getIndexById : function(id) {
48988         for (var i = 0, len = this.config.length; i < len; i++) {
48989             if (this.config[i].id == id) {
48990                 return i;
48991             }
48992         }
48993         return -1;
48994     },
48995
48996     
48997     moveColumn : function(oldIndex, newIndex) {
48998         var config = this.config,
48999             c      = config[oldIndex];
49000             
49001         config.splice(oldIndex, 1);
49002         config.splice(newIndex, 0, c);
49003         this.dataMap = null;
49004         this.fireEvent("columnmoved", this, oldIndex, newIndex);
49005     },
49006
49007     
49008     getColumnCount : function(visibleOnly) {
49009         var length = this.config.length,
49010             c = 0,
49011             i;
49012         
49013         if (visibleOnly === true) {
49014             for (i = 0; i < length; i++) {
49015                 if (!this.isHidden(i)) {
49016                     c++;
49017                 }
49018             }
49019             
49020             return c;
49021         }
49022         
49023         return length;
49024     },
49025
49026     
49027     getColumnsBy : function(fn, scope) {
49028         var config = this.config,
49029             length = config.length,
49030             result = [],
49031             i, c;
49032             
49033         for (i = 0; i < length; i++){
49034             c = config[i];
49035             
49036             if (fn.call(scope || this, c, i) === true) {
49037                 result[result.length] = c;
49038             }
49039         }
49040         
49041         return result;
49042     },
49043
49044     
49045     isSortable : function(col) {
49046         return !!this.config[col].sortable;
49047     },
49048
49049     
49050     isMenuDisabled : function(col) {
49051         return !!this.config[col].menuDisabled;
49052     },
49053
49054     
49055     getRenderer : function(col) {
49056         return this.config[col].renderer || Ext.grid.ColumnModel.defaultRenderer;
49057     },
49058
49059     getRendererScope : function(col) {
49060         return this.config[col].scope;
49061     },
49062
49063     
49064     setRenderer : function(col, fn) {
49065         this.config[col].renderer = fn;
49066     },
49067
49068     
49069     getColumnWidth : function(col) {
49070         var width = this.config[col].width;
49071         if(typeof width != 'number'){
49072             width = this.defaultWidth;
49073         }
49074         return width;
49075     },
49076
49077     
49078     setColumnWidth : function(col, width, suppressEvent) {
49079         this.config[col].width = width;
49080         this.totalWidth = null;
49081         
49082         if (!suppressEvent) {
49083              this.fireEvent("widthchange", this, col, width);
49084         }
49085     },
49086
49087     
49088     getTotalWidth : function(includeHidden) {
49089         if (!this.totalWidth) {
49090             this.totalWidth = 0;
49091             for (var i = 0, len = this.config.length; i < len; i++) {
49092                 if (includeHidden || !this.isHidden(i)) {
49093                     this.totalWidth += this.getColumnWidth(i);
49094                 }
49095             }
49096         }
49097         return this.totalWidth;
49098     },
49099
49100     
49101     getColumnHeader : function(col) {
49102         return this.config[col].header;
49103     },
49104
49105     
49106     setColumnHeader : function(col, header) {
49107         this.config[col].header = header;
49108         this.fireEvent("headerchange", this, col, header);
49109     },
49110
49111     
49112     getColumnTooltip : function(col) {
49113             return this.config[col].tooltip;
49114     },
49115     
49116     setColumnTooltip : function(col, tooltip) {
49117             this.config[col].tooltip = tooltip;
49118     },
49119
49120     
49121     getDataIndex : function(col) {
49122         return this.config[col].dataIndex;
49123     },
49124
49125     
49126     setDataIndex : function(col, dataIndex) {
49127         this.config[col].dataIndex = dataIndex;
49128     },
49129
49130     
49131     findColumnIndex : function(dataIndex) {
49132         var c = this.config;
49133         for(var i = 0, len = c.length; i < len; i++){
49134             if(c[i].dataIndex == dataIndex){
49135                 return i;
49136             }
49137         }
49138         return -1;
49139     },
49140
49141     
49142     isCellEditable : function(colIndex, rowIndex) {
49143         var c = this.config[colIndex],
49144             ed = c.editable;
49145
49146         
49147         return !!(ed || (!Ext.isDefined(ed) && c.editor));
49148     },
49149
49150     
49151     getCellEditor : function(colIndex, rowIndex) {
49152         return this.config[colIndex].getCellEditor(rowIndex);
49153     },
49154
49155     
49156     setEditable : function(col, editable) {
49157         this.config[col].editable = editable;
49158     },
49159
49160     
49161     isHidden : function(colIndex) {
49162         return !!this.config[colIndex].hidden; 
49163     },
49164
49165     
49166     isFixed : function(colIndex) {
49167         return !!this.config[colIndex].fixed;
49168     },
49169
49170     
49171     isResizable : function(colIndex) {
49172         return colIndex >= 0 && this.config[colIndex].resizable !== false && this.config[colIndex].fixed !== true;
49173     },
49174     
49175     
49176     setHidden : function(colIndex, hidden) {
49177         var c = this.config[colIndex];
49178         if(c.hidden !== hidden){
49179             c.hidden = hidden;
49180             this.totalWidth = null;
49181             this.fireEvent("hiddenchange", this, colIndex, hidden);
49182         }
49183     },
49184
49185     
49186     setEditor : function(col, editor) {
49187         this.config[col].setEditor(editor);
49188     },
49189
49190     
49191     destroy : function() {
49192         var length = this.config.length,
49193             i = 0;
49194
49195         for (; i < length; i++){
49196             this.config[i].destroy(); 
49197         }
49198         delete this.config;
49199         delete this.lookup;
49200         this.purgeListeners();
49201     },
49202
49203     
49204     setState : function(col, state) {
49205         state = Ext.applyIf(state, this.defaults);
49206         Ext.apply(this.config[col], state);
49207     }
49208 });
49209
49210
49211 Ext.grid.ColumnModel.defaultRenderer = function(value) {
49212     if (typeof value == "string" && value.length < 1) {
49213         return "&#160;";
49214     }
49215     return value;
49216 };
49217 Ext.grid.AbstractSelectionModel = Ext.extend(Ext.util.Observable,  {
49218     
49219
49220     constructor : function(){
49221         this.locked = false;
49222         Ext.grid.AbstractSelectionModel.superclass.constructor.call(this);
49223     },
49224
49225     
49226     init : function(grid){
49227         this.grid = grid;
49228         if(this.lockOnInit){
49229             delete this.lockOnInit;
49230             this.locked = false;
49231             this.lock();
49232         }
49233         this.initEvents();
49234     },
49235
49236     
49237     lock : function(){
49238         if(!this.locked){
49239             this.locked = true;
49240             
49241             var g = this.grid;
49242             if(g){
49243                 g.getView().on({
49244                     scope: this,
49245                     beforerefresh: this.sortUnLock,
49246                     refresh: this.sortLock
49247                 });
49248             }else{
49249                 this.lockOnInit = true;
49250             }
49251         }
49252     },
49253
49254     
49255     sortLock : function() {
49256         this.locked = true;
49257     },
49258
49259     
49260     sortUnLock : function() {
49261         this.locked = false;
49262     },
49263
49264     
49265     unlock : function(){
49266         if(this.locked){
49267             this.locked = false;
49268             var g = this.grid,
49269                 gv;
49270                 
49271             
49272             if(g){
49273                 gv = g.getView();
49274                 gv.un('beforerefresh', this.sortUnLock, this);
49275                 gv.un('refresh', this.sortLock, this);    
49276             }else{
49277                 delete this.lockOnInit;
49278             }
49279         }
49280     },
49281
49282     
49283     isLocked : function(){
49284         return this.locked;
49285     },
49286
49287     destroy: function(){
49288         this.unlock();
49289         this.purgeListeners();
49290     }
49291 });
49292 Ext.grid.RowSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel,  {
49293     
49294     singleSelect : false,
49295     
49296     constructor : function(config){
49297         Ext.apply(this, config);
49298         this.selections = new Ext.util.MixedCollection(false, function(o){
49299             return o.id;
49300         });
49301
49302         this.last = false;
49303         this.lastActive = false;
49304
49305         this.addEvents(
49306                 
49307                 'selectionchange',
49308                 
49309                 'beforerowselect',
49310                 
49311                 'rowselect',
49312                 
49313                 'rowdeselect'
49314         );
49315         Ext.grid.RowSelectionModel.superclass.constructor.call(this);
49316     },
49317
49318     
49319     
49320     initEvents : function(){
49321
49322         if(!this.grid.enableDragDrop && !this.grid.enableDrag){
49323             this.grid.on('rowmousedown', this.handleMouseDown, this);
49324         }
49325
49326         this.rowNav = new Ext.KeyNav(this.grid.getGridEl(), {
49327             up: this.onKeyPress, 
49328             down: this.onKeyPress,
49329             scope: this
49330         });
49331
49332         this.grid.getView().on({
49333             scope: this,
49334             refresh: this.onRefresh,
49335             rowupdated: this.onRowUpdated,
49336             rowremoved: this.onRemove
49337         });
49338     },
49339     
49340     onKeyPress : function(e, name){
49341         var up = name == 'up',
49342             method = up ? 'selectPrevious' : 'selectNext',
49343             add = up ? -1 : 1,
49344             last;
49345         if(!e.shiftKey || this.singleSelect){
49346             this[method](false);
49347         }else if(this.last !== false && this.lastActive !== false){
49348             last = this.last;
49349             this.selectRange(this.last,  this.lastActive + add);
49350             this.grid.getView().focusRow(this.lastActive);
49351             if(last !== false){
49352                 this.last = last;
49353             }
49354         }else{
49355            this.selectFirstRow();
49356         }
49357     },
49358
49359     
49360     onRefresh : function(){
49361         var ds = this.grid.store,
49362             s = this.getSelections(),
49363             i = 0,
49364             len = s.length, 
49365             index, r;
49366             
49367         this.silent = true;
49368         this.clearSelections(true);
49369         for(; i < len; i++){
49370             r = s[i];
49371             if((index = ds.indexOfId(r.id)) != -1){
49372                 this.selectRow(index, true);
49373             }
49374         }
49375         if(s.length != this.selections.getCount()){
49376             this.fireEvent('selectionchange', this);
49377         }
49378         this.silent = false;
49379     },
49380
49381     
49382     onRemove : function(v, index, r){
49383         if(this.selections.remove(r) !== false){
49384             this.fireEvent('selectionchange', this);
49385         }
49386     },
49387
49388     
49389     onRowUpdated : function(v, index, r){
49390         if(this.isSelected(r)){
49391             v.onRowSelect(index);
49392         }
49393     },
49394
49395     
49396     selectRecords : function(records, keepExisting){
49397         if(!keepExisting){
49398             this.clearSelections();
49399         }
49400         var ds = this.grid.store,
49401             i = 0,
49402             len = records.length;
49403         for(; i < len; i++){
49404             this.selectRow(ds.indexOf(records[i]), true);
49405         }
49406     },
49407
49408     
49409     getCount : function(){
49410         return this.selections.length;
49411     },
49412
49413     
49414     selectFirstRow : function(){
49415         this.selectRow(0);
49416     },
49417
49418     
49419     selectLastRow : function(keepExisting){
49420         this.selectRow(this.grid.store.getCount() - 1, keepExisting);
49421     },
49422
49423     
49424     selectNext : function(keepExisting){
49425         if(this.hasNext()){
49426             this.selectRow(this.last+1, keepExisting);
49427             this.grid.getView().focusRow(this.last);
49428             return true;
49429         }
49430         return false;
49431     },
49432
49433     
49434     selectPrevious : function(keepExisting){
49435         if(this.hasPrevious()){
49436             this.selectRow(this.last-1, keepExisting);
49437             this.grid.getView().focusRow(this.last);
49438             return true;
49439         }
49440         return false;
49441     },
49442
49443     
49444     hasNext : function(){
49445         return this.last !== false && (this.last+1) < this.grid.store.getCount();
49446     },
49447
49448     
49449     hasPrevious : function(){
49450         return !!this.last;
49451     },
49452
49453
49454     
49455     getSelections : function(){
49456         return [].concat(this.selections.items);
49457     },
49458
49459     
49460     getSelected : function(){
49461         return this.selections.itemAt(0);
49462     },
49463
49464     
49465     each : function(fn, scope){
49466         var s = this.getSelections(),
49467             i = 0,
49468             len = s.length;
49469             
49470         for(; i < len; i++){
49471             if(fn.call(scope || this, s[i], i) === false){
49472                 return false;
49473             }
49474         }
49475         return true;
49476     },
49477
49478     
49479     clearSelections : function(fast){
49480         if(this.isLocked()){
49481             return;
49482         }
49483         if(fast !== true){
49484             var ds = this.grid.store,
49485                 s = this.selections;
49486             s.each(function(r){
49487                 this.deselectRow(ds.indexOfId(r.id));
49488             }, this);
49489             s.clear();
49490         }else{
49491             this.selections.clear();
49492         }
49493         this.last = false;
49494     },
49495
49496
49497     
49498     selectAll : function(){
49499         if(this.isLocked()){
49500             return;
49501         }
49502         this.selections.clear();
49503         for(var i = 0, len = this.grid.store.getCount(); i < len; i++){
49504             this.selectRow(i, true);
49505         }
49506     },
49507
49508     
49509     hasSelection : function(){
49510         return this.selections.length > 0;
49511     },
49512
49513     
49514     isSelected : function(index){
49515         var r = Ext.isNumber(index) ? this.grid.store.getAt(index) : index;
49516         return (r && this.selections.key(r.id) ? true : false);
49517     },
49518
49519     
49520     isIdSelected : function(id){
49521         return (this.selections.key(id) ? true : false);
49522     },
49523
49524     
49525     handleMouseDown : function(g, rowIndex, e){
49526         if(e.button !== 0 || this.isLocked()){
49527             return;
49528         }
49529         var view = this.grid.getView();
49530         if(e.shiftKey && !this.singleSelect && this.last !== false){
49531             var last = this.last;
49532             this.selectRange(last, rowIndex, e.ctrlKey);
49533             this.last = last; 
49534             view.focusRow(rowIndex);
49535         }else{
49536             var isSelected = this.isSelected(rowIndex);
49537             if(e.ctrlKey && isSelected){
49538                 this.deselectRow(rowIndex);
49539             }else if(!isSelected || this.getCount() > 1){
49540                 this.selectRow(rowIndex, e.ctrlKey || e.shiftKey);
49541                 view.focusRow(rowIndex);
49542             }
49543         }
49544     },
49545
49546     
49547     selectRows : function(rows, keepExisting){
49548         if(!keepExisting){
49549             this.clearSelections();
49550         }
49551         for(var i = 0, len = rows.length; i < len; i++){
49552             this.selectRow(rows[i], true);
49553         }
49554     },
49555
49556     
49557     selectRange : function(startRow, endRow, keepExisting){
49558         var i;
49559         if(this.isLocked()){
49560             return;
49561         }
49562         if(!keepExisting){
49563             this.clearSelections();
49564         }
49565         if(startRow <= endRow){
49566             for(i = startRow; i <= endRow; i++){
49567                 this.selectRow(i, true);
49568             }
49569         }else{
49570             for(i = startRow; i >= endRow; i--){
49571                 this.selectRow(i, true);
49572             }
49573         }
49574     },
49575
49576     
49577     deselectRange : function(startRow, endRow, preventViewNotify){
49578         if(this.isLocked()){
49579             return;
49580         }
49581         for(var i = startRow; i <= endRow; i++){
49582             this.deselectRow(i, preventViewNotify);
49583         }
49584     },
49585
49586     
49587     selectRow : function(index, keepExisting, preventViewNotify){
49588         if(this.isLocked() || (index < 0 || index >= this.grid.store.getCount()) || (keepExisting && this.isSelected(index))){
49589             return;
49590         }
49591         var r = this.grid.store.getAt(index);
49592         if(r && this.fireEvent('beforerowselect', this, index, keepExisting, r) !== false){
49593             if(!keepExisting || this.singleSelect){
49594                 this.clearSelections();
49595             }
49596             this.selections.add(r);
49597             this.last = this.lastActive = index;
49598             if(!preventViewNotify){
49599                 this.grid.getView().onRowSelect(index);
49600             }
49601             if(!this.silent){
49602                 this.fireEvent('rowselect', this, index, r);
49603                 this.fireEvent('selectionchange', this);
49604             }
49605         }
49606     },
49607
49608     
49609     deselectRow : function(index, preventViewNotify){
49610         if(this.isLocked()){
49611             return;
49612         }
49613         if(this.last == index){
49614             this.last = false;
49615         }
49616         if(this.lastActive == index){
49617             this.lastActive = false;
49618         }
49619         var r = this.grid.store.getAt(index);
49620         if(r){
49621             this.selections.remove(r);
49622             if(!preventViewNotify){
49623                 this.grid.getView().onRowDeselect(index);
49624             }
49625             this.fireEvent('rowdeselect', this, index, r);
49626             this.fireEvent('selectionchange', this);
49627         }
49628     },
49629
49630     
49631     acceptsNav : function(row, col, cm){
49632         return !cm.isHidden(col) && cm.isCellEditable(col, row);
49633     },
49634
49635     
49636     onEditorKey : function(field, e){
49637         var k = e.getKey(), 
49638             newCell, 
49639             g = this.grid, 
49640             last = g.lastEdit,
49641             ed = g.activeEditor,
49642             shift = e.shiftKey,
49643             ae, last, r, c;
49644             
49645         if(k == e.TAB){
49646             e.stopEvent();
49647             ed.completeEdit();
49648             if(shift){
49649                 newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
49650             }else{
49651                 newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
49652             }
49653         }else if(k == e.ENTER){
49654             if(this.moveEditorOnEnter !== false){
49655                 if(shift){
49656                     newCell = g.walkCells(last.row - 1, last.col, -1, this.acceptsNav, this);
49657                 }else{
49658                     newCell = g.walkCells(last.row + 1, last.col, 1, this.acceptsNav, this);
49659                 }
49660             }
49661         }
49662         if(newCell){
49663             r = newCell[0];
49664             c = newCell[1];
49665
49666             this.onEditorSelect(r, last.row);
49667
49668             if(g.isEditor && g.editing){ 
49669                 ae = g.activeEditor;
49670                 if(ae && ae.field.triggerBlur){
49671                     
49672                     ae.field.triggerBlur();
49673                 }
49674             }
49675             g.startEditing(r, c);
49676         }
49677     },
49678     
49679     onEditorSelect: function(row, lastRow){
49680         if(lastRow != row){
49681             this.selectRow(row); 
49682         }
49683     },
49684     
49685     destroy : function(){
49686         Ext.destroy(this.rowNav);
49687         this.rowNav = null;
49688         Ext.grid.RowSelectionModel.superclass.destroy.call(this);
49689     }
49690 });
49691
49692 Ext.grid.Column = Ext.extend(Ext.util.Observable, {
49693     
49694     
49695     
49696     
49697     
49698     
49699     
49700     
49701     
49702     
49703     
49704     
49705     
49706     
49707     
49708     
49709     
49710     
49711     
49712     
49713     
49714     
49715
49716     
49717     isColumn : true,
49718
49719     constructor : function(config){
49720         Ext.apply(this, config);
49721
49722         if(Ext.isString(this.renderer)){
49723             this.renderer = Ext.util.Format[this.renderer];
49724         }else if(Ext.isObject(this.renderer)){
49725             this.scope = this.renderer.scope;
49726             this.renderer = this.renderer.fn;
49727         }
49728         if(!this.scope){
49729             this.scope = this;
49730         }
49731
49732         var ed = this.editor;
49733         delete this.editor;
49734         this.setEditor(ed);
49735         this.addEvents(
49736             
49737             'click',
49738             
49739             'contextmenu',
49740             
49741             'dblclick',
49742             
49743             'mousedown'
49744         );
49745         Ext.grid.Column.superclass.constructor.call(this);
49746     },
49747
49748     
49749     processEvent : function(name, e, grid, rowIndex, colIndex){
49750         return this.fireEvent(name, this, grid, rowIndex, e);
49751     },
49752
49753     
49754     destroy: function() {
49755         if(this.setEditor){
49756             this.setEditor(null);
49757         }
49758         this.purgeListeners();
49759     },
49760
49761     
49762     renderer : function(value){
49763         return value;
49764     },
49765
49766     
49767     getEditor: function(rowIndex){
49768         return this.editable !== false ? this.editor : null;
49769     },
49770
49771     
49772     setEditor : function(editor){
49773         var ed = this.editor;
49774         if(ed){
49775             if(ed.gridEditor){
49776                 ed.gridEditor.destroy();
49777                 delete ed.gridEditor;
49778             }else{
49779                 ed.destroy();
49780             }
49781         }
49782         this.editor = null;
49783         if(editor){
49784             
49785             if(!editor.isXType){
49786                 editor = Ext.create(editor, 'textfield');
49787             }
49788             this.editor = editor;
49789         }
49790     },
49791
49792     
49793     getCellEditor: function(rowIndex){
49794         var ed = this.getEditor(rowIndex);
49795         if(ed){
49796             if(!ed.startEdit){
49797                 if(!ed.gridEditor){
49798                     ed.gridEditor = new Ext.grid.GridEditor(ed);
49799                 }
49800                 ed = ed.gridEditor;
49801             }
49802         }
49803         return ed;
49804     }
49805 });
49806
49807
49808 Ext.grid.BooleanColumn = Ext.extend(Ext.grid.Column, {
49809     
49810     trueText: 'true',
49811     
49812     falseText: 'false',
49813     
49814     undefinedText: '&#160;',
49815
49816     constructor: function(cfg){
49817         Ext.grid.BooleanColumn.superclass.constructor.call(this, cfg);
49818         var t = this.trueText, f = this.falseText, u = this.undefinedText;
49819         this.renderer = function(v){
49820             if(v === undefined){
49821                 return u;
49822             }
49823             if(!v || v === 'false'){
49824                 return f;
49825             }
49826             return t;
49827         };
49828     }
49829 });
49830
49831
49832 Ext.grid.NumberColumn = Ext.extend(Ext.grid.Column, {
49833     
49834     format : '0,000.00',
49835     constructor: function(cfg){
49836         Ext.grid.NumberColumn.superclass.constructor.call(this, cfg);
49837         this.renderer = Ext.util.Format.numberRenderer(this.format);
49838     }
49839 });
49840
49841
49842 Ext.grid.DateColumn = Ext.extend(Ext.grid.Column, {
49843     
49844     format : 'm/d/Y',
49845     constructor: function(cfg){
49846         Ext.grid.DateColumn.superclass.constructor.call(this, cfg);
49847         this.renderer = Ext.util.Format.dateRenderer(this.format);
49848     }
49849 });
49850
49851
49852 Ext.grid.TemplateColumn = Ext.extend(Ext.grid.Column, {
49853     
49854     constructor: function(cfg){
49855         Ext.grid.TemplateColumn.superclass.constructor.call(this, cfg);
49856         var tpl = (!Ext.isPrimitive(this.tpl) && this.tpl.compile) ? this.tpl : new Ext.XTemplate(this.tpl);
49857         this.renderer = function(value, p, r){
49858             return tpl.apply(r.data);
49859         };
49860         this.tpl = tpl;
49861     }
49862 });
49863
49864
49865 Ext.grid.ActionColumn = Ext.extend(Ext.grid.Column, {
49866     
49867     
49868     
49869     
49870     
49871     
49872     
49873     
49874     header: '&#160;',
49875
49876     actionIdRe: /x-action-col-(\d+)/,
49877     
49878     
49879     altText: '',
49880
49881     constructor: function(cfg) {
49882         var me = this,
49883             items = cfg.items || (me.items = [me]),
49884             l = items.length,
49885             i,
49886             item;
49887
49888         Ext.grid.ActionColumn.superclass.constructor.call(me, cfg);
49889
49890
49891
49892         me.renderer = function(v, meta) {
49893
49894             v = Ext.isFunction(cfg.renderer) ? cfg.renderer.apply(this, arguments)||'' : '';
49895
49896             meta.css += ' x-action-col-cell';
49897             for (i = 0; i < l; i++) {
49898                 item = items[i];
49899                 v += '<img alt="' + me.altText + '" src="' + (item.icon || Ext.BLANK_IMAGE_URL) +
49900                     '" class="x-action-col-icon x-action-col-' + String(i) + ' ' + (item.iconCls || '') +
49901                     ' ' + (Ext.isFunction(item.getClass) ? item.getClass.apply(item.scope||this.scope||this, arguments) : '') + '"' +
49902                     ((item.tooltip) ? ' ext:qtip="' + item.tooltip + '"' : '') + ' />';
49903             }
49904             return v;
49905         };
49906     },
49907
49908     destroy: function() {
49909         delete this.items;
49910         delete this.renderer;
49911         return Ext.grid.ActionColumn.superclass.destroy.apply(this, arguments);
49912     },
49913
49914     
49915     processEvent : function(name, e, grid, rowIndex, colIndex){
49916         var m = e.getTarget().className.match(this.actionIdRe),
49917             item, fn;
49918         if (m && (item = this.items[parseInt(m[1], 10)])) {
49919             if (name == 'click') {
49920                 (fn = item.handler || this.handler) && fn.call(item.scope||this.scope||this, grid, rowIndex, colIndex, item, e);
49921             } else if ((name == 'mousedown') && (item.stopSelection !== false)) {
49922                 return false;
49923             }
49924         }
49925         return Ext.grid.ActionColumn.superclass.processEvent.apply(this, arguments);
49926     }
49927 });
49928
49929
49930 Ext.grid.Column.types = {
49931     gridcolumn : Ext.grid.Column,
49932     booleancolumn: Ext.grid.BooleanColumn,
49933     numbercolumn: Ext.grid.NumberColumn,
49934     datecolumn: Ext.grid.DateColumn,
49935     templatecolumn: Ext.grid.TemplateColumn,
49936     actioncolumn: Ext.grid.ActionColumn
49937 };
49938 Ext.grid.RowNumberer = Ext.extend(Object, {
49939     
49940     header: "",
49941     
49942     width: 23,
49943     
49944     sortable: false,
49945     
49946     constructor : function(config){
49947         Ext.apply(this, config);
49948         if(this.rowspan){
49949             this.renderer = this.renderer.createDelegate(this);
49950         }
49951     },
49952
49953     
49954     fixed:true,
49955     hideable: false,
49956     menuDisabled:true,
49957     dataIndex: '',
49958     id: 'numberer',
49959     rowspan: undefined,
49960
49961     
49962     renderer : function(v, p, record, rowIndex){
49963         if(this.rowspan){
49964             p.cellAttr = 'rowspan="'+this.rowspan+'"';
49965         }
49966         return rowIndex+1;
49967     }
49968 });
49969 Ext.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.RowSelectionModel, {
49970
49971     
49972     
49973     header : '<div class="x-grid3-hd-checker">&#160;</div>',
49974     
49975     width : 20,
49976     
49977     sortable : false,
49978
49979     
49980     menuDisabled : true,
49981     fixed : true,
49982     hideable: false,
49983     dataIndex : '',
49984     id : 'checker',
49985     isColumn: true, 
49986
49987     constructor : function(){
49988         Ext.grid.CheckboxSelectionModel.superclass.constructor.apply(this, arguments);
49989         if(this.checkOnly){
49990             this.handleMouseDown = Ext.emptyFn;
49991         }
49992     },
49993
49994     
49995     initEvents : function(){
49996         Ext.grid.CheckboxSelectionModel.superclass.initEvents.call(this);
49997         this.grid.on('render', function(){
49998             Ext.fly(this.grid.getView().innerHd).on('mousedown', this.onHdMouseDown, this);
49999         }, this);
50000     },
50001
50002     
50003     processEvent : function(name, e, grid, rowIndex, colIndex){
50004         if (name == 'mousedown') {
50005             this.onMouseDown(e, e.getTarget());
50006             return false;
50007         } else {
50008             return Ext.grid.Column.prototype.processEvent.apply(this, arguments);
50009         }
50010     },
50011
50012     
50013     onMouseDown : function(e, t){
50014         if(e.button === 0 && t.className == 'x-grid3-row-checker'){ 
50015             e.stopEvent();
50016             var row = e.getTarget('.x-grid3-row');
50017             if(row){
50018                 var index = row.rowIndex;
50019                 if(this.isSelected(index)){
50020                     this.deselectRow(index);
50021                 }else{
50022                     this.selectRow(index, true);
50023                     this.grid.getView().focusRow(index);
50024                 }
50025             }
50026         }
50027     },
50028
50029     
50030     onHdMouseDown : function(e, t) {
50031         if(t.className == 'x-grid3-hd-checker'){
50032             e.stopEvent();
50033             var hd = Ext.fly(t.parentNode);
50034             var isChecked = hd.hasClass('x-grid3-hd-checker-on');
50035             if(isChecked){
50036                 hd.removeClass('x-grid3-hd-checker-on');
50037                 this.clearSelections();
50038             }else{
50039                 hd.addClass('x-grid3-hd-checker-on');
50040                 this.selectAll();
50041             }
50042         }
50043     },
50044
50045     
50046     renderer : function(v, p, record){
50047         return '<div class="x-grid3-row-checker">&#160;</div>';
50048     },
50049     
50050     onEditorSelect: function(row, lastRow){
50051         if(lastRow != row && !this.checkOnly){
50052             this.selectRow(row); 
50053         }
50054     }
50055 });
50056 Ext.grid.CellSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel,  {
50057     
50058     constructor : function(config){
50059         Ext.apply(this, config);
50060
50061             this.selection = null;
50062         
50063             this.addEvents(
50064                 
50065                 "beforecellselect",
50066                 
50067                 "cellselect",
50068                 
50069                 "selectionchange"
50070             );
50071         
50072             Ext.grid.CellSelectionModel.superclass.constructor.call(this);
50073     },
50074
50075     
50076     initEvents : function(){
50077         this.grid.on('cellmousedown', this.handleMouseDown, this);
50078         this.grid.on(Ext.EventManager.getKeyEvent(), this.handleKeyDown, this);
50079         this.grid.getView().on({
50080             scope: this,
50081             refresh: this.onViewChange,
50082             rowupdated: this.onRowUpdated,
50083             beforerowremoved: this.clearSelections,
50084             beforerowsinserted: this.clearSelections
50085         });
50086         if(this.grid.isEditor){
50087             this.grid.on('beforeedit', this.beforeEdit,  this);
50088         }
50089     },
50090
50091         
50092     beforeEdit : function(e){
50093         this.select(e.row, e.column, false, true, e.record);
50094     },
50095
50096         
50097     onRowUpdated : function(v, index, r){
50098         if(this.selection && this.selection.record == r){
50099             v.onCellSelect(index, this.selection.cell[1]);
50100         }
50101     },
50102
50103         
50104     onViewChange : function(){
50105         this.clearSelections(true);
50106     },
50107
50108         
50109     getSelectedCell : function(){
50110         return this.selection ? this.selection.cell : null;
50111     },
50112
50113     
50114     clearSelections : function(preventNotify){
50115         var s = this.selection;
50116         if(s){
50117             if(preventNotify !== true){
50118                 this.grid.view.onCellDeselect(s.cell[0], s.cell[1]);
50119             }
50120             this.selection = null;
50121             this.fireEvent("selectionchange", this, null);
50122         }
50123     },
50124
50125     
50126     hasSelection : function(){
50127         return this.selection ? true : false;
50128     },
50129
50130     
50131     handleMouseDown : function(g, row, cell, e){
50132         if(e.button !== 0 || this.isLocked()){
50133             return;
50134         }
50135         this.select(row, cell);
50136     },
50137
50138     
50139     select : function(rowIndex, colIndex, preventViewNotify, preventFocus,  r){
50140         if(this.fireEvent("beforecellselect", this, rowIndex, colIndex) !== false){
50141             this.clearSelections();
50142             r = r || this.grid.store.getAt(rowIndex);
50143             this.selection = {
50144                 record : r,
50145                 cell : [rowIndex, colIndex]
50146             };
50147             if(!preventViewNotify){
50148                 var v = this.grid.getView();
50149                 v.onCellSelect(rowIndex, colIndex);
50150                 if(preventFocus !== true){
50151                     v.focusCell(rowIndex, colIndex);
50152                 }
50153             }
50154             this.fireEvent("cellselect", this, rowIndex, colIndex);
50155             this.fireEvent("selectionchange", this, this.selection);
50156         }
50157     },
50158
50159         
50160     isSelectable : function(rowIndex, colIndex, cm){
50161         return !cm.isHidden(colIndex);
50162     },
50163     
50164     
50165     onEditorKey: function(field, e){
50166         if(e.getKey() == e.TAB){
50167             this.handleKeyDown(e);
50168         }
50169     },
50170
50171     
50172     handleKeyDown : function(e){
50173         if(!e.isNavKeyPress()){
50174             return;
50175         }
50176         
50177         var k = e.getKey(),
50178             g = this.grid,
50179             s = this.selection,
50180             sm = this,
50181             walk = function(row, col, step){
50182                 return g.walkCells(
50183                     row,
50184                     col,
50185                     step,
50186                     g.isEditor && g.editing ? sm.acceptsNav : sm.isSelectable, 
50187                     sm
50188                 );
50189             },
50190             cell, newCell, r, c, ae;
50191
50192         switch(k){
50193             case e.ESC:
50194             case e.PAGE_UP:
50195             case e.PAGE_DOWN:
50196                 
50197                 break;
50198             default:
50199                 
50200                 e.stopEvent();
50201                 break;
50202         }
50203
50204         if(!s){
50205             cell = walk(0, 0, 1); 
50206             if(cell){
50207                 this.select(cell[0], cell[1]);
50208             }
50209             return;
50210         }
50211
50212         cell = s.cell;  
50213         r = cell[0];    
50214         c = cell[1];    
50215         
50216         switch(k){
50217             case e.TAB:
50218                 if(e.shiftKey){
50219                     newCell = walk(r, c - 1, -1);
50220                 }else{
50221                     newCell = walk(r, c + 1, 1);
50222                 }
50223                 break;
50224             case e.DOWN:
50225                 newCell = walk(r + 1, c, 1);
50226                 break;
50227             case e.UP:
50228                 newCell = walk(r - 1, c, -1);
50229                 break;
50230             case e.RIGHT:
50231                 newCell = walk(r, c + 1, 1);
50232                 break;
50233             case e.LEFT:
50234                 newCell = walk(r, c - 1, -1);
50235                 break;
50236             case e.ENTER:
50237                 if (g.isEditor && !g.editing) {
50238                     g.startEditing(r, c);
50239                     return;
50240                 }
50241                 break;
50242         }
50243
50244         if(newCell){
50245             
50246             r = newCell[0];
50247             c = newCell[1];
50248
50249             this.select(r, c); 
50250
50251             if(g.isEditor && g.editing){ 
50252                 ae = g.activeEditor;
50253                 if(ae && ae.field.triggerBlur){
50254                     
50255                     ae.field.triggerBlur();
50256                 }
50257                 g.startEditing(r, c);
50258             }
50259         }
50260     },
50261
50262     acceptsNav : function(row, col, cm){
50263         return !cm.isHidden(col) && cm.isCellEditable(col, row);
50264     }
50265 });
50266 Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {
50267     
50268     clicksToEdit: 2,
50269
50270     
50271     forceValidation: false,
50272
50273     
50274     isEditor : true,
50275     
50276     detectEdit: false,
50277
50278     
50279     autoEncode : false,
50280
50281     
50282     
50283     trackMouseOver: false, 
50284
50285     
50286     initComponent : function(){
50287         Ext.grid.EditorGridPanel.superclass.initComponent.call(this);
50288
50289         if(!this.selModel){
50290             
50291             this.selModel = new Ext.grid.CellSelectionModel();
50292         }
50293
50294         this.activeEditor = null;
50295
50296         this.addEvents(
50297             
50298             "beforeedit",
50299             
50300             "afteredit",
50301             
50302             "validateedit"
50303         );
50304     },
50305
50306     
50307     initEvents : function(){
50308         Ext.grid.EditorGridPanel.superclass.initEvents.call(this);
50309
50310         this.getGridEl().on('mousewheel', this.stopEditing.createDelegate(this, [true]), this);
50311         this.on('columnresize', this.stopEditing, this, [true]);
50312
50313         if(this.clicksToEdit == 1){
50314             this.on("cellclick", this.onCellDblClick, this);
50315         }else {
50316             var view = this.getView();
50317             if(this.clicksToEdit == 'auto' && view.mainBody){
50318                 view.mainBody.on('mousedown', this.onAutoEditClick, this);
50319             }
50320             this.on('celldblclick', this.onCellDblClick, this);
50321         }
50322     },
50323
50324     onResize : function(){
50325         Ext.grid.EditorGridPanel.superclass.onResize.apply(this, arguments);
50326         var ae = this.activeEditor;
50327         if(this.editing && ae){
50328             ae.realign(true);
50329         }
50330     },
50331
50332     
50333     onCellDblClick : function(g, row, col){
50334         this.startEditing(row, col);
50335     },
50336
50337     
50338     onAutoEditClick : function(e, t){
50339         if(e.button !== 0){
50340             return;
50341         }
50342         var row = this.view.findRowIndex(t),
50343             col = this.view.findCellIndex(t);
50344         if(row !== false && col !== false){
50345             this.stopEditing();
50346             if(this.selModel.getSelectedCell){ 
50347                 var sc = this.selModel.getSelectedCell();
50348                 if(sc && sc[0] === row && sc[1] === col){
50349                     this.startEditing(row, col);
50350                 }
50351             }else{
50352                 if(this.selModel.isSelected(row)){
50353                     this.startEditing(row, col);
50354                 }
50355             }
50356         }
50357     },
50358
50359     
50360     onEditComplete : function(ed, value, startValue){
50361         this.editing = false;
50362         this.lastActiveEditor = this.activeEditor;
50363         this.activeEditor = null;
50364
50365         var r = ed.record,
50366             field = this.colModel.getDataIndex(ed.col);
50367         value = this.postEditValue(value, startValue, r, field);
50368         if(this.forceValidation === true || String(value) !== String(startValue)){
50369             var e = {
50370                 grid: this,
50371                 record: r,
50372                 field: field,
50373                 originalValue: startValue,
50374                 value: value,
50375                 row: ed.row,
50376                 column: ed.col,
50377                 cancel:false
50378             };
50379             if(this.fireEvent("validateedit", e) !== false && !e.cancel && String(value) !== String(startValue)){
50380                 r.set(field, e.value);
50381                 delete e.cancel;
50382                 this.fireEvent("afteredit", e);
50383             }
50384         }
50385         this.view.focusCell(ed.row, ed.col);
50386     },
50387
50388     
50389     startEditing : function(row, col){
50390         this.stopEditing();
50391         if(this.colModel.isCellEditable(col, row)){
50392             this.view.ensureVisible(row, col, true);
50393             var r = this.store.getAt(row),
50394                 field = this.colModel.getDataIndex(col),
50395                 e = {
50396                     grid: this,
50397                     record: r,
50398                     field: field,
50399                     value: r.data[field],
50400                     row: row,
50401                     column: col,
50402                     cancel:false
50403                 };
50404             if(this.fireEvent("beforeedit", e) !== false && !e.cancel){
50405                 this.editing = true;
50406                 var ed = this.colModel.getCellEditor(col, row);
50407                 if(!ed){
50408                     return;
50409                 }
50410                 if(!ed.rendered){
50411                     ed.parentEl = this.view.getEditorParent(ed);
50412                     ed.on({
50413                         scope: this,
50414                         render: {
50415                             fn: function(c){
50416                                 c.field.focus(false, true);
50417                             },
50418                             single: true,
50419                             scope: this
50420                         },
50421                         specialkey: function(field, e){
50422                             this.getSelectionModel().onEditorKey(field, e);
50423                         },
50424                         complete: this.onEditComplete,
50425                         canceledit: this.stopEditing.createDelegate(this, [true])
50426                     });
50427                 }
50428                 Ext.apply(ed, {
50429                     row     : row,
50430                     col     : col,
50431                     record  : r
50432                 });
50433                 this.lastEdit = {
50434                     row: row,
50435                     col: col
50436                 };
50437                 this.activeEditor = ed;
50438                 
50439                 
50440                 ed.selectSameEditor = (this.activeEditor == this.lastActiveEditor);
50441                 var v = this.preEditValue(r, field);
50442                 ed.startEdit(this.view.getCell(row, col).firstChild, Ext.isDefined(v) ? v : '');
50443
50444                 
50445                 (function(){
50446                     delete ed.selectSameEditor;
50447                 }).defer(50);
50448             }
50449         }
50450     },
50451
50452     
50453     preEditValue : function(r, field){
50454         var value = r.data[field];
50455         return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlDecode(value) : value;
50456     },
50457
50458     
50459     postEditValue : function(value, originalValue, r, field){
50460         return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlEncode(value) : value;
50461     },
50462
50463     
50464     stopEditing : function(cancel){
50465         if(this.editing){
50466             
50467             var ae = this.lastActiveEditor = this.activeEditor;
50468             if(ae){
50469                 ae[cancel === true ? 'cancelEdit' : 'completeEdit']();
50470                 this.view.focusCell(ae.row, ae.col);
50471             }
50472             this.activeEditor = null;
50473         }
50474         this.editing = false;
50475     }
50476 });
50477 Ext.reg('editorgrid', Ext.grid.EditorGridPanel);
50478
50479 Ext.grid.GridEditor = function(field, config){
50480     Ext.grid.GridEditor.superclass.constructor.call(this, field, config);
50481     field.monitorTab = false;
50482 };
50483
50484 Ext.extend(Ext.grid.GridEditor, Ext.Editor, {
50485     alignment: "tl-tl",
50486     autoSize: "width",
50487     hideEl : false,
50488     cls: "x-small-editor x-grid-editor",
50489     shim:false,
50490     shadow:false
50491 });
50492 Ext.grid.PropertyRecord = Ext.data.Record.create([
50493     {name:'name',type:'string'}, 'value'
50494 ]);
50495
50496
50497 Ext.grid.PropertyStore = Ext.extend(Ext.util.Observable, {
50498     
50499     constructor : function(grid, source){
50500         this.grid = grid;
50501         this.store = new Ext.data.Store({
50502             recordType : Ext.grid.PropertyRecord
50503         });
50504         this.store.on('update', this.onUpdate,  this);
50505         if(source){
50506             this.setSource(source);
50507         }
50508         Ext.grid.PropertyStore.superclass.constructor.call(this);    
50509     },
50510     
50511     
50512     setSource : function(o){
50513         this.source = o;
50514         this.store.removeAll();
50515         var data = [];
50516         for(var k in o){
50517             if(this.isEditableValue(o[k])){
50518                 data.push(new Ext.grid.PropertyRecord({name: k, value: o[k]}, k));
50519             }
50520         }
50521         this.store.loadRecords({records: data}, {}, true);
50522     },
50523
50524     
50525     onUpdate : function(ds, record, type){
50526         if(type == Ext.data.Record.EDIT){
50527             var v = record.data.value;
50528             var oldValue = record.modified.value;
50529             if(this.grid.fireEvent('beforepropertychange', this.source, record.id, v, oldValue) !== false){
50530                 this.source[record.id] = v;
50531                 record.commit();
50532                 this.grid.fireEvent('propertychange', this.source, record.id, v, oldValue);
50533             }else{
50534                 record.reject();
50535             }
50536         }
50537     },
50538
50539     
50540     getProperty : function(row){
50541        return this.store.getAt(row);
50542     },
50543
50544     
50545     isEditableValue: function(val){
50546         return Ext.isPrimitive(val) || Ext.isDate(val);
50547     },
50548
50549     
50550     setValue : function(prop, value, create){
50551         var r = this.getRec(prop);
50552         if(r){
50553             r.set('value', value);
50554             this.source[prop] = value;
50555         }else if(create){
50556             
50557             this.source[prop] = value;
50558             r = new Ext.grid.PropertyRecord({name: prop, value: value}, prop);
50559             this.store.add(r);
50560
50561         }
50562     },
50563     
50564     
50565     remove : function(prop){
50566         var r = this.getRec(prop);
50567         if(r){
50568             this.store.remove(r);
50569             delete this.source[prop];
50570         }
50571     },
50572     
50573     
50574     getRec : function(prop){
50575         return this.store.getById(prop);
50576     },
50577
50578     
50579     getSource : function(){
50580         return this.source;
50581     }
50582 });
50583
50584
50585 Ext.grid.PropertyColumnModel = Ext.extend(Ext.grid.ColumnModel, {
50586     
50587     nameText : 'Name',
50588     valueText : 'Value',
50589     dateFormat : 'm/j/Y',
50590     trueText: 'true',
50591     falseText: 'false',
50592     
50593     constructor : function(grid, store){
50594         var g = Ext.grid,
50595                 f = Ext.form;
50596                 
50597             this.grid = grid;
50598             g.PropertyColumnModel.superclass.constructor.call(this, [
50599                 {header: this.nameText, width:50, sortable: true, dataIndex:'name', id: 'name', menuDisabled:true},
50600                 {header: this.valueText, width:50, resizable:false, dataIndex: 'value', id: 'value', menuDisabled:true}
50601             ]);
50602             this.store = store;
50603         
50604             var bfield = new f.Field({
50605                 autoCreate: {tag: 'select', children: [
50606                     {tag: 'option', value: 'true', html: this.trueText},
50607                     {tag: 'option', value: 'false', html: this.falseText}
50608                 ]},
50609                 getValue : function(){
50610                     return this.el.dom.value == 'true';
50611                 }
50612             });
50613             this.editors = {
50614                 'date' : new g.GridEditor(new f.DateField({selectOnFocus:true})),
50615                 'string' : new g.GridEditor(new f.TextField({selectOnFocus:true})),
50616                 'number' : new g.GridEditor(new f.NumberField({selectOnFocus:true, style:'text-align:left;'})),
50617                 'boolean' : new g.GridEditor(bfield, {
50618                     autoSize: 'both'
50619                 })
50620             };
50621             this.renderCellDelegate = this.renderCell.createDelegate(this);
50622             this.renderPropDelegate = this.renderProp.createDelegate(this);
50623     },
50624
50625     
50626     renderDate : function(dateVal){
50627         return dateVal.dateFormat(this.dateFormat);
50628     },
50629
50630     
50631     renderBool : function(bVal){
50632         return this[bVal ? 'trueText' : 'falseText'];
50633     },
50634
50635     
50636     isCellEditable : function(colIndex, rowIndex){
50637         return colIndex == 1;
50638     },
50639
50640     
50641     getRenderer : function(col){
50642         return col == 1 ?
50643             this.renderCellDelegate : this.renderPropDelegate;
50644     },
50645
50646     
50647     renderProp : function(v){
50648         return this.getPropertyName(v);
50649     },
50650
50651     
50652     renderCell : function(val, meta, rec){
50653         var renderer = this.grid.customRenderers[rec.get('name')];
50654         if(renderer){
50655             return renderer.apply(this, arguments);
50656         }
50657         var rv = val;
50658         if(Ext.isDate(val)){
50659             rv = this.renderDate(val);
50660         }else if(typeof val == 'boolean'){
50661             rv = this.renderBool(val);
50662         }
50663         return Ext.util.Format.htmlEncode(rv);
50664     },
50665
50666     
50667     getPropertyName : function(name){
50668         var pn = this.grid.propertyNames;
50669         return pn && pn[name] ? pn[name] : name;
50670     },
50671
50672     
50673     getCellEditor : function(colIndex, rowIndex){
50674         var p = this.store.getProperty(rowIndex),
50675             n = p.data.name, 
50676             val = p.data.value;
50677         if(this.grid.customEditors[n]){
50678             return this.grid.customEditors[n];
50679         }
50680         if(Ext.isDate(val)){
50681             return this.editors.date;
50682         }else if(typeof val == 'number'){
50683             return this.editors.number;
50684         }else if(typeof val == 'boolean'){
50685             return this.editors['boolean'];
50686         }else{
50687             return this.editors.string;
50688         }
50689     },
50690
50691     
50692     destroy : function(){
50693         Ext.grid.PropertyColumnModel.superclass.destroy.call(this);
50694         this.destroyEditors(this.editors);
50695         this.destroyEditors(this.grid.customEditors);
50696     },
50697     
50698     destroyEditors: function(editors){
50699         for(var ed in editors){
50700             Ext.destroy(editors[ed]);
50701         }
50702     }
50703 });
50704
50705
50706 Ext.grid.PropertyGrid = Ext.extend(Ext.grid.EditorGridPanel, {
50707     
50708     
50709     
50710     
50711     
50712
50713     
50714     enableColumnMove:false,
50715     stripeRows:false,
50716     trackMouseOver: false,
50717     clicksToEdit:1,
50718     enableHdMenu : false,
50719     viewConfig : {
50720         forceFit:true
50721     },
50722
50723     
50724     initComponent : function(){
50725         this.customRenderers = this.customRenderers || {};
50726         this.customEditors = this.customEditors || {};
50727         this.lastEditRow = null;
50728         var store = new Ext.grid.PropertyStore(this);
50729         this.propStore = store;
50730         var cm = new Ext.grid.PropertyColumnModel(this, store);
50731         store.store.sort('name', 'ASC');
50732         this.addEvents(
50733             
50734             'beforepropertychange',
50735             
50736             'propertychange'
50737         );
50738         this.cm = cm;
50739         this.ds = store.store;
50740         Ext.grid.PropertyGrid.superclass.initComponent.call(this);
50741
50742                 this.mon(this.selModel, 'beforecellselect', function(sm, rowIndex, colIndex){
50743             if(colIndex === 0){
50744                 this.startEditing.defer(200, this, [rowIndex, 1]);
50745                 return false;
50746             }
50747         }, this);
50748     },
50749
50750     
50751     onRender : function(){
50752         Ext.grid.PropertyGrid.superclass.onRender.apply(this, arguments);
50753
50754         this.getGridEl().addClass('x-props-grid');
50755     },
50756
50757     
50758     afterRender: function(){
50759         Ext.grid.PropertyGrid.superclass.afterRender.apply(this, arguments);
50760         if(this.source){
50761             this.setSource(this.source);
50762         }
50763     },
50764
50765     
50766     setSource : function(source){
50767         this.propStore.setSource(source);
50768     },
50769
50770     
50771     getSource : function(){
50772         return this.propStore.getSource();
50773     },
50774     
50775     
50776     setProperty : function(prop, value, create){
50777         this.propStore.setValue(prop, value, create);    
50778     },
50779     
50780     
50781     removeProperty : function(prop){
50782         this.propStore.remove(prop);
50783     }
50784
50785     
50786     
50787     
50788     
50789 });
50790 Ext.reg("propertygrid", Ext.grid.PropertyGrid);
50791
50792 Ext.grid.GroupingView = Ext.extend(Ext.grid.GridView, {
50793
50794     
50795     groupByText : 'Group By This Field',
50796     
50797     showGroupsText : 'Show in Groups',
50798     
50799     hideGroupedColumn : false,
50800     
50801     showGroupName : true,
50802     
50803     startCollapsed : false,
50804     
50805     enableGrouping : true,
50806     
50807     enableGroupingMenu : true,
50808     
50809     enableNoGroups : true,
50810     
50811     emptyGroupText : '(None)',
50812     
50813     ignoreAdd : false,
50814     
50815     groupTextTpl : '{text}',
50816
50817     
50818     groupMode: 'value',
50819
50820     
50821     
50822     
50823     cancelEditOnToggle: true,
50824
50825     
50826     initTemplates : function(){
50827         Ext.grid.GroupingView.superclass.initTemplates.call(this);
50828         this.state = {};
50829
50830         var sm = this.grid.getSelectionModel();
50831         sm.on(sm.selectRow ? 'beforerowselect' : 'beforecellselect',
50832                 this.onBeforeRowSelect, this);
50833
50834         if(!this.startGroup){
50835             this.startGroup = new Ext.XTemplate(
50836                 '<div id="{groupId}" class="x-grid-group {cls}">',
50837                     '<div id="{groupId}-hd" class="x-grid-group-hd" style="{style}"><div class="x-grid-group-title">', this.groupTextTpl ,'</div></div>',
50838                     '<div id="{groupId}-bd" class="x-grid-group-body">'
50839             );
50840         }
50841         this.startGroup.compile();
50842
50843         if (!this.endGroup) {
50844             this.endGroup = '</div></div>';
50845         }
50846     },
50847
50848     
50849     findGroup : function(el){
50850         return Ext.fly(el).up('.x-grid-group', this.mainBody.dom);
50851     },
50852
50853     
50854     getGroups : function(){
50855         return this.hasRows() ? this.mainBody.dom.childNodes : [];
50856     },
50857
50858     
50859     onAdd : function(ds, records, index) {
50860         if (this.canGroup() && !this.ignoreAdd) {
50861             var ss = this.getScrollState();
50862             this.fireEvent('beforerowsinserted', ds, index, index + (records.length-1));
50863             this.refresh();
50864             this.restoreScroll(ss);
50865             this.fireEvent('rowsinserted', ds, index, index + (records.length-1));
50866         } else if (!this.canGroup()) {
50867             Ext.grid.GroupingView.superclass.onAdd.apply(this, arguments);
50868         }
50869     },
50870
50871     
50872     onRemove : function(ds, record, index, isUpdate){
50873         Ext.grid.GroupingView.superclass.onRemove.apply(this, arguments);
50874         var g = document.getElementById(record._groupId);
50875         if(g && g.childNodes[1].childNodes.length < 1){
50876             Ext.removeNode(g);
50877         }
50878         this.applyEmptyText();
50879     },
50880
50881     
50882     refreshRow : function(record){
50883         if(this.ds.getCount()==1){
50884             this.refresh();
50885         }else{
50886             this.isUpdating = true;
50887             Ext.grid.GroupingView.superclass.refreshRow.apply(this, arguments);
50888             this.isUpdating = false;
50889         }
50890     },
50891
50892     
50893     beforeMenuShow : function(){
50894         var item, items = this.hmenu.items, disabled = this.cm.config[this.hdCtxIndex].groupable === false;
50895         if((item = items.get('groupBy'))){
50896             item.setDisabled(disabled);
50897         }
50898         if((item = items.get('showGroups'))){
50899             item.setDisabled(disabled);
50900             item.setChecked(this.canGroup(), true);
50901         }
50902     },
50903
50904     
50905     renderUI : function(){
50906         var markup = Ext.grid.GroupingView.superclass.renderUI.call(this);
50907
50908         if(this.enableGroupingMenu && this.hmenu){
50909             this.hmenu.add('-',{
50910                 itemId:'groupBy',
50911                 text: this.groupByText,
50912                 handler: this.onGroupByClick,
50913                 scope: this,
50914                 iconCls:'x-group-by-icon'
50915             });
50916             if(this.enableNoGroups){
50917                 this.hmenu.add({
50918                     itemId:'showGroups',
50919                     text: this.showGroupsText,
50920                     checked: true,
50921                     checkHandler: this.onShowGroupsClick,
50922                     scope: this
50923                 });
50924             }
50925             this.hmenu.on('beforeshow', this.beforeMenuShow, this);
50926         }
50927         return markup;
50928     },
50929
50930     processEvent: function(name, e){
50931         Ext.grid.GroupingView.superclass.processEvent.call(this, name, e);
50932         var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
50933         if(hd){
50934             
50935             var field = this.getGroupField(),
50936                 prefix = this.getPrefix(field),
50937                 groupValue = hd.id.substring(prefix.length),
50938                 emptyRe = new RegExp('gp-' + Ext.escapeRe(field) + '--hd');
50939
50940             
50941             groupValue = groupValue.substr(0, groupValue.length - 3);
50942             
50943             
50944             if(groupValue || emptyRe.test(hd.id)){
50945                 this.grid.fireEvent('group' + name, this.grid, field, groupValue, e);
50946             }
50947             if(name == 'mousedown' && e.button == 0){
50948                 this.toggleGroup(hd.parentNode);
50949             }
50950         }
50951
50952     },
50953
50954     
50955     onGroupByClick : function(){
50956         var grid = this.grid;
50957         this.enableGrouping = true;
50958         grid.store.groupBy(this.cm.getDataIndex(this.hdCtxIndex));
50959         grid.fireEvent('groupchange', grid, grid.store.getGroupState());
50960         this.beforeMenuShow(); 
50961         this.refresh();
50962     },
50963
50964     
50965     onShowGroupsClick : function(mi, checked){
50966         this.enableGrouping = checked;
50967         if(checked){
50968             this.onGroupByClick();
50969         }else{
50970             this.grid.store.clearGrouping();
50971             this.grid.fireEvent('groupchange', this, null);
50972         }
50973     },
50974
50975     
50976     toggleRowIndex : function(rowIndex, expanded){
50977         if(!this.canGroup()){
50978             return;
50979         }
50980         var row = this.getRow(rowIndex);
50981         if(row){
50982             this.toggleGroup(this.findGroup(row), expanded);
50983         }
50984     },
50985
50986     
50987     toggleGroup : function(group, expanded){
50988         var gel = Ext.get(group);
50989         expanded = Ext.isDefined(expanded) ? expanded : gel.hasClass('x-grid-group-collapsed');
50990         if(this.state[gel.id] !== expanded){
50991             if (this.cancelEditOnToggle !== false) {
50992                 this.grid.stopEditing(true);
50993             }
50994             this.state[gel.id] = expanded;
50995             gel[expanded ? 'removeClass' : 'addClass']('x-grid-group-collapsed');
50996         }
50997     },
50998
50999     
51000     toggleAllGroups : function(expanded){
51001         var groups = this.getGroups();
51002         for(var i = 0, len = groups.length; i < len; i++){
51003             this.toggleGroup(groups[i], expanded);
51004         }
51005     },
51006
51007     
51008     expandAllGroups : function(){
51009         this.toggleAllGroups(true);
51010     },
51011
51012     
51013     collapseAllGroups : function(){
51014         this.toggleAllGroups(false);
51015     },
51016
51017     
51018     getGroup : function(v, r, groupRenderer, rowIndex, colIndex, ds){
51019         var column = this.cm.config[colIndex],
51020             g = groupRenderer ? groupRenderer.call(column.scope, v, {}, r, rowIndex, colIndex, ds) : String(v);
51021         if(g === '' || g === '&#160;'){
51022             g = column.emptyGroupText || this.emptyGroupText;
51023         }
51024         return g;
51025     },
51026
51027     
51028     getGroupField : function(){
51029         return this.grid.store.getGroupState();
51030     },
51031
51032     
51033     afterRender : function(){
51034         if(!this.ds || !this.cm){
51035             return;
51036         }
51037         Ext.grid.GroupingView.superclass.afterRender.call(this);
51038         if(this.grid.deferRowRender){
51039             this.updateGroupWidths();
51040         }
51041     },
51042     
51043     afterRenderUI: function () {
51044         Ext.grid.GroupingView.superclass.afterRenderUI.call(this);
51045
51046         if (this.enableGroupingMenu && this.hmenu) {
51047             this.hmenu.add('-',{
51048                 itemId:'groupBy',
51049                 text: this.groupByText,
51050                 handler: this.onGroupByClick,
51051                 scope: this,
51052                 iconCls:'x-group-by-icon'
51053             });
51054             
51055             if (this.enableNoGroups) {
51056                 this.hmenu.add({
51057                     itemId:'showGroups',
51058                     text: this.showGroupsText,
51059                     checked: true,
51060                     checkHandler: this.onShowGroupsClick,
51061                     scope: this
51062                 });
51063             }
51064             
51065             this.hmenu.on('beforeshow', this.beforeMenuShow, this);
51066         }
51067     },
51068
51069     
51070     renderRows : function(){
51071         var groupField = this.getGroupField();
51072         var eg = !!groupField;
51073         
51074         if(this.hideGroupedColumn) {
51075             var colIndex = this.cm.findColumnIndex(groupField),
51076                 hasLastGroupField = Ext.isDefined(this.lastGroupField);
51077             if(!eg && hasLastGroupField){
51078                 this.mainBody.update('');
51079                 this.cm.setHidden(this.cm.findColumnIndex(this.lastGroupField), false);
51080                 delete this.lastGroupField;
51081             }else if (eg && !hasLastGroupField){
51082                 this.lastGroupField = groupField;
51083                 this.cm.setHidden(colIndex, true);
51084             }else if (eg && hasLastGroupField && groupField !== this.lastGroupField) {
51085                 this.mainBody.update('');
51086                 var oldIndex = this.cm.findColumnIndex(this.lastGroupField);
51087                 this.cm.setHidden(oldIndex, false);
51088                 this.lastGroupField = groupField;
51089                 this.cm.setHidden(colIndex, true);
51090             }
51091         }
51092         return Ext.grid.GroupingView.superclass.renderRows.apply(
51093                     this, arguments);
51094     },
51095
51096     
51097     doRender : function(cs, rs, ds, startRow, colCount, stripe){
51098         if(rs.length < 1){
51099             return '';
51100         }
51101
51102         if(!this.canGroup() || this.isUpdating){
51103             return Ext.grid.GroupingView.superclass.doRender.apply(this, arguments);
51104         }
51105
51106         var groupField = this.getGroupField(),
51107             colIndex = this.cm.findColumnIndex(groupField),
51108             g,
51109             gstyle = 'width:' + this.getTotalWidth() + ';',
51110             cfg = this.cm.config[colIndex],
51111             groupRenderer = cfg.groupRenderer || cfg.renderer,
51112             prefix = this.showGroupName ? (cfg.groupName || cfg.header)+': ' : '',
51113             groups = [],
51114             curGroup, i, len, gid;
51115
51116         for(i = 0, len = rs.length; i < len; i++){
51117             var rowIndex = startRow + i,
51118                 r = rs[i],
51119                 gvalue = r.data[groupField];
51120
51121                 g = this.getGroup(gvalue, r, groupRenderer, rowIndex, colIndex, ds);
51122             if(!curGroup || curGroup.group != g){
51123                 gid = this.constructId(gvalue, groupField, colIndex);
51124                 
51125                 
51126                 this.state[gid] = !(Ext.isDefined(this.state[gid]) ? !this.state[gid] : this.startCollapsed);
51127                 curGroup = {
51128                     group: g,
51129                     gvalue: gvalue,
51130                     text: prefix + g,
51131                     groupId: gid,
51132                     startRow: rowIndex,
51133                     rs: [r],
51134                     cls: this.state[gid] ? '' : 'x-grid-group-collapsed',
51135                     style: gstyle
51136                 };
51137                 groups.push(curGroup);
51138             }else{
51139                 curGroup.rs.push(r);
51140             }
51141             r._groupId = gid;
51142         }
51143
51144         var buf = [];
51145         for(i = 0, len = groups.length; i < len; i++){
51146             g = groups[i];
51147             this.doGroupStart(buf, g, cs, ds, colCount);
51148             buf[buf.length] = Ext.grid.GroupingView.superclass.doRender.call(
51149                     this, cs, g.rs, ds, g.startRow, colCount, stripe);
51150
51151             this.doGroupEnd(buf, g, cs, ds, colCount);
51152         }
51153         return buf.join('');
51154     },
51155
51156     
51157     getGroupId : function(value){
51158         var field = this.getGroupField();
51159         return this.constructId(value, field, this.cm.findColumnIndex(field));
51160     },
51161
51162     
51163     constructId : function(value, field, idx){
51164         var cfg = this.cm.config[idx],
51165             groupRenderer = cfg.groupRenderer || cfg.renderer,
51166             val = (this.groupMode == 'value') ? value : this.getGroup(value, {data:{}}, groupRenderer, 0, idx, this.ds);
51167
51168         return this.getPrefix(field) + Ext.util.Format.htmlEncode(val);
51169     },
51170
51171     
51172     canGroup  : function(){
51173         return this.enableGrouping && !!this.getGroupField();
51174     },
51175
51176     
51177     getPrefix: function(field){
51178         return this.grid.getGridEl().id + '-gp-' + field + '-';
51179     },
51180
51181     
51182     doGroupStart : function(buf, g, cs, ds, colCount){
51183         buf[buf.length] = this.startGroup.apply(g);
51184     },
51185
51186     
51187     doGroupEnd : function(buf, g, cs, ds, colCount){
51188         buf[buf.length] = this.endGroup;
51189     },
51190
51191     
51192     getRows : function(){
51193         if(!this.canGroup()){
51194             return Ext.grid.GroupingView.superclass.getRows.call(this);
51195         }
51196         var r = [],
51197             gs = this.getGroups(),
51198             g,
51199             i = 0,
51200             len = gs.length,
51201             j,
51202             jlen;
51203         for(; i < len; ++i){
51204             g = gs[i].childNodes[1];
51205             if(g){
51206                 g = g.childNodes;
51207                 for(j = 0, jlen = g.length; j < jlen; ++j){
51208                     r[r.length] = g[j];
51209                 }
51210             }
51211         }
51212         return r;
51213     },
51214
51215     
51216     updateGroupWidths : function(){
51217         if(!this.canGroup() || !this.hasRows()){
51218             return;
51219         }
51220         var tw = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth-this.getScrollOffset()) +'px';
51221         var gs = this.getGroups();
51222         for(var i = 0, len = gs.length; i < len; i++){
51223             gs[i].firstChild.style.width = tw;
51224         }
51225     },
51226
51227     
51228     onColumnWidthUpdated : function(col, w, tw){
51229         Ext.grid.GroupingView.superclass.onColumnWidthUpdated.call(this, col, w, tw);
51230         this.updateGroupWidths();
51231     },
51232
51233     
51234     onAllColumnWidthsUpdated : function(ws, tw){
51235         Ext.grid.GroupingView.superclass.onAllColumnWidthsUpdated.call(this, ws, tw);
51236         this.updateGroupWidths();
51237     },
51238
51239     
51240     onColumnHiddenUpdated : function(col, hidden, tw){
51241         Ext.grid.GroupingView.superclass.onColumnHiddenUpdated.call(this, col, hidden, tw);
51242         this.updateGroupWidths();
51243     },
51244
51245     
51246     onLayout : function(){
51247         this.updateGroupWidths();
51248     },
51249
51250     
51251     onBeforeRowSelect : function(sm, rowIndex){
51252         this.toggleRowIndex(rowIndex, true);
51253     }
51254 });
51255
51256 Ext.grid.GroupingView.GROUP_ID = 1000;